Merge "Clean up InputChannel file descriptor data type."
diff --git a/api/current.txt b/api/current.txt
index 9a1d394b..97be454 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -992,6 +992,7 @@
field public static final int textColorTertiary = 16843282; // 0x1010212
field public static final int textColorTertiaryInverse = 16843283; // 0x1010213
field public static final int textCursorDrawable = 16843618; // 0x1010362
+ field public static final int textDirection = 16843688; // 0x10103a8
field public static final int textEditNoPasteWindowLayout = 16843541; // 0x1010315
field public static final int textEditPasteWindowLayout = 16843540; // 0x1010314
field public static final int textEditSideNoPasteWindowLayout = 16843615; // 0x101035f
@@ -20478,6 +20479,19 @@
method public int getTopPadding();
}
+ public abstract interface TextDirectionHeuristic {
+ }
+
+ public class TextDirectionHeuristics {
+ ctor public TextDirectionHeuristics();
+ field public static final android.text.TextDirectionHeuristic ANYRTL_LTR;
+ field public static final android.text.TextDirectionHeuristic FIRSTSTRONG_LTR;
+ field public static final android.text.TextDirectionHeuristic FIRSTSTRONG_RTL;
+ field public static final android.text.TextDirectionHeuristic LOCALE;
+ field public static final android.text.TextDirectionHeuristic LTR;
+ field public static final android.text.TextDirectionHeuristic RTL;
+ }
+
public class TextPaint extends android.graphics.Paint {
ctor public TextPaint();
ctor public TextPaint(int);
@@ -23171,6 +23185,7 @@
method public final android.view.ViewParent getParent();
method public float getPivotX();
method public float getPivotY();
+ method public int getResolvedTextDirection();
method public android.content.res.Resources getResources();
method public final int getRight();
method protected float getRightFadingEdgeStrength();
@@ -23190,6 +23205,7 @@
method public int getSystemUiVisibility();
method public java.lang.Object getTag();
method public java.lang.Object getTag(int);
+ method public int getTextDirection();
method public final int getTop();
method protected float getTopFadingEdgeStrength();
method protected int getTopPaddingOffset();
@@ -23321,8 +23337,10 @@
method public void requestLayout();
method public boolean requestRectangleOnScreen(android.graphics.Rect);
method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean);
+ method protected void resetResolvedTextDirection();
method public static int resolveSize(int, int);
method public static int resolveSizeAndState(int, int, int);
+ method protected void resolveTextDirection();
method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>);
method public void saveHierarchyState(android.util.SparseArray<android.os.Parcelable>);
method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
@@ -23402,6 +23420,7 @@
method public void setSystemUiVisibility(int);
method public void setTag(java.lang.Object);
method public void setTag(int, java.lang.Object);
+ method public void setTextDirection(int);
method public final void setTop(int);
method public void setTouchDelegate(android.view.TouchDelegate);
method public void setTranslationX(float);
@@ -23424,6 +23443,7 @@
method public boolean willNotCacheDrawing();
method public boolean willNotDraw();
field public static final android.util.Property ALPHA;
+ field protected static int DEFAULT_TEXT_DIRECTION;
field public static final int DRAWING_CACHE_QUALITY_AUTO = 0; // 0x0
field public static final int DRAWING_CACHE_QUALITY_HIGH = 1048576; // 0x100000
field public static final int DRAWING_CACHE_QUALITY_LOW = 524288; // 0x80000
@@ -23500,6 +23520,12 @@
field public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 2; // 0x2
field public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 1; // 0x1
field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
+ field public static final int TEXT_DIRECTION_ANY_RTL = 2; // 0x2
+ field public static final int TEXT_DIRECTION_FIRST_STRONG = 1; // 0x1
+ field public static final int TEXT_DIRECTION_INHERIT = 0; // 0x0
+ field public static final int TEXT_DIRECTION_LOCALE = 5; // 0x5
+ field public static final int TEXT_DIRECTION_LTR = 3; // 0x3
+ field public static final int TEXT_DIRECTION_RTL = 4; // 0x4
field public static final android.util.Property TRANSLATION_X;
field public static final android.util.Property TRANSLATION_Y;
field protected static final java.lang.String VIEW_LOG_TAG = "View";
@@ -23766,7 +23792,6 @@
method public boolean requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
method public void requestTransparentRegion(android.view.View);
method protected void resetResolvedLayoutDirection();
- method protected void resetResolvedTextDirection();
method public void scheduleLayoutAnimation();
method public void setAddStatesFromChildren(boolean);
method public void setAlwaysDrawnWithCacheEnabled(boolean);
@@ -26407,10 +26432,12 @@
field public static final android.widget.GridLayout.Alignment BASELINE;
field public static final android.widget.GridLayout.Alignment BOTTOM;
field public static final android.widget.GridLayout.Alignment CENTER;
+ field public static final android.widget.GridLayout.Alignment END;
field public static final android.widget.GridLayout.Alignment FILL;
field public static final int HORIZONTAL = 0; // 0x0
field public static final android.widget.GridLayout.Alignment LEFT;
field public static final android.widget.GridLayout.Alignment RIGHT;
+ field public static final android.widget.GridLayout.Alignment START;
field public static final android.widget.GridLayout.Alignment TOP;
field public static final int UNDEFINED = -2147483648; // 0x80000000
field public static final int VERTICAL = 1; // 0x1
@@ -27593,7 +27620,6 @@
method protected void resetResolvedDrawables();
method protected void resetResolvedLayoutDirection();
method protected void resolveDrawables();
- method protected void resolveTextDirection();
method public void setAllCaps(boolean);
method public final void setAutoLinkMask(int);
method public void setCompoundDrawablePadding(int);
diff --git a/cmds/keystore/keystore.cpp b/cmds/keystore/keystore.cpp
index 05f77e5..2c9cb35 100644
--- a/cmds/keystore/keystore.cpp
+++ b/cmds/keystore/keystore.cpp
@@ -581,7 +581,7 @@
static ResponseCode insert(KeyStore* keyStore, int sock, uid_t uid, Value* keyName, Value* val) {
char filename[NAME_MAX];
encode_key(filename, uid, keyName);
- Blob keyBlob(val->value, val->length, 0, NULL);
+ Blob keyBlob(val->value, val->length, NULL, 0);
return keyStore->put(filename, &keyBlob);
}
diff --git a/core/java/android/text/TextDirectionHeuristics.java b/core/java/android/text/TextDirectionHeuristics.java
index e5c1e5b..ae41eab 100644
--- a/core/java/android/text/TextDirectionHeuristics.java
+++ b/core/java/android/text/TextDirectionHeuristics.java
@@ -17,13 +17,10 @@
package android.text;
-import java.util.Locale;
-
import android.util.LocaleUtil;
/**
* Some objects that implement TextDirectionHeuristic.
- * @hide
*/
public class TextDirectionHeuristics {
@@ -74,9 +71,8 @@
* Computes the text direction based on an algorithm. Subclasses implement
* {@link #defaultIsRtl} to handle cases where the algorithm cannot determine the
* direction from the text alone.
- * @hide
*/
- public static abstract class TextDirectionHeuristicImpl implements TextDirectionHeuristic {
+ private static abstract class TextDirectionHeuristicImpl implements TextDirectionHeuristic {
private final TextDirectionAlgorithm mAlgorithm;
public TextDirectionHeuristicImpl(TextDirectionAlgorithm algorithm) {
@@ -157,13 +153,11 @@
/**
* Interface for an algorithm to guess the direction of a paragraph of text.
*
- * @hide
*/
- public static interface TextDirectionAlgorithm {
+ private static interface TextDirectionAlgorithm {
/**
* Returns whether the range of text is RTL according to the algorithm.
*
- * @hide
*/
TriState checkRtl(char[] text, int start, int count);
}
@@ -173,9 +167,8 @@
* the paragraph direction. This is the standard Unicode Bidirectional
* algorithm.
*
- * @hide
*/
- public static class FirstStrong implements TextDirectionAlgorithm {
+ private static class FirstStrong implements TextDirectionAlgorithm {
@Override
public TriState checkRtl(char[] text, int start, int count) {
TriState result = TriState.UNKNOWN;
@@ -196,9 +189,8 @@
* character (e.g. excludes LRE, LRO, RLE, RLO) to determine the
* direction of text.
*
- * @hide
*/
- public static class AnyStrong implements TextDirectionAlgorithm {
+ private static class AnyStrong implements TextDirectionAlgorithm {
private final boolean mLookForRtl;
@Override
@@ -239,7 +231,7 @@
/**
* Algorithm that uses the Locale direction to force the direction of a paragraph.
*/
- public static class TextDirectionHeuristicLocale extends TextDirectionHeuristicImpl {
+ private static class TextDirectionHeuristicLocale extends TextDirectionHeuristicImpl {
public TextDirectionHeuristicLocale() {
super(null);
diff --git a/core/java/android/text/method/KeyListener.java b/core/java/android/text/method/KeyListener.java
index 8594852..318149a 100644
--- a/core/java/android/text/method/KeyListener.java
+++ b/core/java/android/text/method/KeyListener.java
@@ -22,7 +22,7 @@
/**
* Interface for converting text key events into edit operations on an
- * Editable class. Note that for must cases this interface has been
+ * Editable class. Note that for most cases this interface has been
* superceded by general soft input methods as defined by
* {@link android.view.inputmethod.InputMethod}; it should only be used
* for cases where an application has its own on-screen keypad and also wants
diff --git a/core/java/android/text/method/TransformationMethod.java b/core/java/android/text/method/TransformationMethod.java
index 9f51c2a..b542109 100644
--- a/core/java/android/text/method/TransformationMethod.java
+++ b/core/java/android/text/method/TransformationMethod.java
@@ -18,7 +18,6 @@
import android.graphics.Rect;
import android.view.View;
-import android.widget.TextView;
/**
* TextView uses TransformationMethods to do things like replacing the
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 9e8a228..1932c7f 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -39,6 +39,7 @@
import javax.microedition.khronos.opengles.GL;
import java.io.File;
+import java.io.PrintWriter;
import static javax.microedition.khronos.egl.EGL10.*;
@@ -84,13 +85,27 @@
static final String DISABLE_VSYNC_PROPERTY = "hwui.disable_vsync";
/**
+ * System property used to enable or disable hardware rendering profiling.
+ * The default value of this property is assumed to be false.
+ *
+ * When profiling is enabled, the adb shell dumpsys gfxinfo command will
+ * output extra information about the time taken to execute by the last
+ * frames.
+ *
+ * Possible values:
+ * "true", to enable profiling
+ * "false", to disable profiling
+ */
+ static final String PROFILE_PROPERTY = "hwui.profile";
+
+ /**
* System property used to debug EGL configuration choice.
*
* Possible values:
* "choice", print the chosen configuration only
* "all", print all possible configurations
*/
- static final String PRINT_CONFIG_PROPERTY = "hwui.print_config";
+ static final String PRINT_CONFIG_PROPERTY = "hwui.print_config";
/**
* Turn on to draw dirty regions every other frame.
@@ -112,6 +127,16 @@
*/
public static boolean sSystemRendererDisabled = false;
+ /**
+ * Number of frames to profile.
+ */
+ private static final int PROFILE_MAX_FRAMES = 64;
+
+ /**
+ * Number of floats per profiled frame.
+ */
+ private static final int PROFILE_FRAME_DATA_COUNT = 3;
+
private boolean mEnabled;
private boolean mRequested = true;
@@ -226,6 +251,12 @@
abstract HardwareCanvas getCanvas();
/**
+ * Outputs extra debugging information in the specified file descriptor.
+ * @param pw
+ */
+ abstract void dumpGfxInfo(PrintWriter pw);
+
+ /**
* Sets the directory to use as a persistent storage for hardware rendering
* resources.
*
@@ -439,6 +470,7 @@
GL mGl;
HardwareCanvas mCanvas;
+
int mFrameCount;
Paint mDebugPaint;
@@ -456,6 +488,10 @@
final boolean mVsyncDisabled;
+ final boolean mProfileEnabled;
+ final float[] mProfileData;
+ int mProfileCurrentFrame = -PROFILE_FRAME_DATA_COUNT;
+
final int mGlVersion;
final boolean mTranslucent;
@@ -472,6 +508,34 @@
if (mVsyncDisabled) {
Log.d(LOG_TAG, "Disabling v-sync");
}
+
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ if (!ViewDebug.DEBUG_LATENCY) {
+ final String profileProperty = SystemProperties.get(PROFILE_PROPERTY, "false");
+ mProfileEnabled = "true".equalsIgnoreCase(profileProperty);
+ if (mProfileEnabled) {
+ Log.d(LOG_TAG, "Profiling hardware renderer");
+ }
+ } else {
+ mProfileEnabled = true;
+ }
+
+ if (mProfileEnabled) {
+ mProfileData = new float[PROFILE_MAX_FRAMES * PROFILE_FRAME_DATA_COUNT];
+ } else {
+ mProfileData = null;
+ }
+ }
+
+ @Override
+ void dumpGfxInfo(PrintWriter pw) {
+ if (mProfileEnabled) {
+ pw.printf("\n\tDraw\tProcess\tExecute\n");
+ for (int i = 0; i < mProfileData.length; i += PROFILE_FRAME_DATA_COUNT) {
+ pw.printf("\t%3.2f\t%3.2f\t%3.2f\n", mProfileData[i], mProfileData[i + 1],
+ mProfileData[i + 2]);
+ }
+ }
}
/**
@@ -860,34 +924,49 @@
(view.mPrivateFlags & View.INVALIDATED) == View.INVALIDATED;
view.mPrivateFlags &= ~View.INVALIDATED;
- final long getDisplayListStartTime;
- if (ViewDebug.DEBUG_LATENCY) {
+ long getDisplayListStartTime = 0;
+ if (mProfileEnabled) {
+ mProfileCurrentFrame += PROFILE_FRAME_DATA_COUNT;
+ if (mProfileCurrentFrame >= mProfileData.length) {
+ mProfileCurrentFrame = 0;
+ }
+
getDisplayListStartTime = System.nanoTime();
}
DisplayList displayList = view.getDisplayList();
- if (ViewDebug.DEBUG_LATENCY) {
+ if (mProfileEnabled) {
long now = System.nanoTime();
- Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- getDisplayList() took "
- + ((now - getDisplayListStartTime) * 0.000001f) + "ms");
+ float total = (now - getDisplayListStartTime) * 0.000001f;
+ //noinspection PointlessArithmeticExpression
+ mProfileData[mProfileCurrentFrame] = total;
+
+ if (ViewDebug.DEBUG_LATENCY) {
+ Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- getDisplayList() took " +
+ total + "ms");
+ }
}
if (displayList != null) {
- final long drawDisplayListStartTime;
- if (ViewDebug.DEBUG_LATENCY) {
+ long drawDisplayListStartTime = 0;
+ if (mProfileEnabled) {
drawDisplayListStartTime = System.nanoTime();
}
- boolean invalidateNeeded = canvas.drawDisplayList(
- displayList, view.getWidth(),
- view.getHeight(), mRedrawClip);
+ boolean invalidateNeeded = canvas.drawDisplayList(displayList,
+ view.getWidth(), view.getHeight(), mRedrawClip);
- if (ViewDebug.DEBUG_LATENCY) {
+ if (mProfileEnabled) {
long now = System.nanoTime();
- Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- drawDisplayList() took "
- + ((now - drawDisplayListStartTime) * 0.000001f)
- + "ms, invalidateNeeded=" + invalidateNeeded + ".");
+ float total = (now - drawDisplayListStartTime) * 0.000001f;
+ mProfileData[mProfileCurrentFrame + 1] = total;
+
+ if (ViewDebug.DEBUG_LATENCY) {
+ Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- drawDisplayList() took " +
+ total + "ms, invalidateNeeded=" +
+ invalidateNeeded + ".");
+ }
}
if (invalidateNeeded) {
@@ -922,17 +1001,22 @@
attachInfo.mIgnoreDirtyState = false;
- final long eglSwapBuffersStartTime;
- if (ViewDebug.DEBUG_LATENCY) {
+ long eglSwapBuffersStartTime = 0;
+ if (mProfileEnabled) {
eglSwapBuffersStartTime = System.nanoTime();
}
sEgl.eglSwapBuffers(sEglDisplay, mEglSurface);
- if (ViewDebug.DEBUG_LATENCY) {
+ if (mProfileEnabled) {
long now = System.nanoTime();
- Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- eglSwapBuffers() took "
- + ((now - eglSwapBuffersStartTime) * 0.000001f) + "ms");
+ float total = (now - eglSwapBuffersStartTime) * 0.000001f;
+ mProfileData[mProfileCurrentFrame + 2] = total;
+
+ if (ViewDebug.DEBUG_LATENCY) {
+ Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- eglSwapBuffers() took " +
+ total + "ms");
+ }
}
checkEglErrors();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7658d04..87104f4 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -65,6 +65,7 @@
import android.view.accessibility.AccessibilityNodeProvider;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
+import android.view.animation.Transformation;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
@@ -2617,7 +2618,6 @@
/**
* Text direction is inherited thru {@link ViewGroup}
- * @hide
*/
public static final int TEXT_DIRECTION_INHERIT = 0;
@@ -2626,7 +2626,6 @@
* determines the paragraph direction. If there is no strong directional character, the
* paragraph direction is the view's resolved layout direction.
*
- * @hide
*/
public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
@@ -2635,42 +2634,36 @@
* any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
* If there are neither, the paragraph direction is the view's resolved layout direction.
*
- * @hide
*/
public static final int TEXT_DIRECTION_ANY_RTL = 2;
/**
* Text direction is forced to LTR.
*
- * @hide
*/
public static final int TEXT_DIRECTION_LTR = 3;
/**
* Text direction is forced to RTL.
*
- * @hide
*/
public static final int TEXT_DIRECTION_RTL = 4;
/**
* Text direction is coming from the system Locale.
*
- * @hide
*/
public static final int TEXT_DIRECTION_LOCALE = 5;
/**
* Default text direction is inherited
*
- * @hide
*/
protected static int DEFAULT_TEXT_DIRECTION = TEXT_DIRECTION_INHERIT;
/**
* The text direction that has been defined by {@link #setTextDirection(int)}.
*
- * {@hide}
*/
@ViewDebug.ExportedProperty(category = "text", mapping = {
@ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
@@ -2688,7 +2681,6 @@
* not TEXT_DIRECTION_INHERIT, otherwise resolution proceeds up the parent
* chain of the view.
*
- * {@hide}
*/
@ViewDebug.ExportedProperty(category = "text", mapping = {
@ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
@@ -3774,14 +3766,6 @@
}
if ((mPrivateFlags & FOCUSED) != 0) {
- // If this is the first focusable do not clear focus since the we
- // try to give it focus every time a view clears its focus. Hence,
- // the view that would gain focus already has it.
- View firstFocusable = getFirstFocusable();
- if (firstFocusable == this) {
- return;
- }
-
mPrivateFlags &= ~FOCUSED;
if (mParent != null) {
@@ -3790,24 +3774,9 @@
onFocusChanged(false, 0, null);
refreshDrawableState();
-
- // The view cleared focus and invoked the callbacks, so now is the
- // time to give focus to the the first focusable to ensure that the
- // gain focus is announced after clear focus.
- if (firstFocusable != null) {
- firstFocusable.requestFocus(FOCUS_FORWARD);
- }
}
}
- private View getFirstFocusable() {
- ViewRootImpl viewRoot = getViewRootImpl();
- if (viewRoot != null) {
- return viewRoot.focusSearch(null, FOCUS_FORWARD);
- }
- return null;
- }
-
/**
* Called to clear the focus of a view that is about to be removed.
* Doesn't call clearChildFocus, which prevents this view from taking
@@ -8252,6 +8221,9 @@
throw new NullPointerException("Layout parameters cannot be null");
}
mLayoutParams = params;
+ if (mParent instanceof ViewGroup) {
+ ((ViewGroup) mParent).onSetLayoutParams(this, params);
+ }
requestLayout();
}
@@ -10947,6 +10919,346 @@
}
/**
+ * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
+ * case of an active Animation being run on the view.
+ */
+ private boolean drawAnimation(ViewGroup parent, long drawingTime,
+ Animation a, boolean scalingRequired) {
+ Transformation invalidationTransform;
+ final int flags = parent.mGroupFlags;
+ final boolean initialized = a.isInitialized();
+ if (!initialized) {
+ a.initialize(mRight - mLeft, mBottom - mTop, getWidth(), getHeight());
+ a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
+ onAnimationStart();
+ }
+
+ boolean more = a.getTransformation(drawingTime, parent.mChildTransformation, 1f);
+ if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
+ if (parent.mInvalidationTransformation == null) {
+ parent.mInvalidationTransformation = new Transformation();
+ }
+ invalidationTransform = parent.mInvalidationTransformation;
+ a.getTransformation(drawingTime, invalidationTransform, 1f);
+ } else {
+ invalidationTransform = parent.mChildTransformation;
+ }
+ if (more) {
+ if (!a.willChangeBounds()) {
+ if ((flags & (parent.FLAG_OPTIMIZE_INVALIDATE | parent.FLAG_ANIMATION_DONE)) ==
+ parent.FLAG_OPTIMIZE_INVALIDATE) {
+ parent.mGroupFlags |= parent.FLAG_INVALIDATE_REQUIRED;
+ } else if ((flags & parent.FLAG_INVALIDATE_REQUIRED) == 0) {
+ // The child need to draw an animation, potentially offscreen, so
+ // make sure we do not cancel invalidate requests
+ parent.mPrivateFlags |= DRAW_ANIMATION;
+ parent.invalidate(mLeft, mTop, mRight, mBottom);
+ }
+ } else {
+ if (parent.mInvalidateRegion == null) {
+ parent.mInvalidateRegion = new RectF();
+ }
+ final RectF region = parent.mInvalidateRegion;
+ a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
+ invalidationTransform);
+
+ // The child need to draw an animation, potentially offscreen, so
+ // make sure we do not cancel invalidate requests
+ parent.mPrivateFlags |= DRAW_ANIMATION;
+
+ final int left = mLeft + (int) region.left;
+ final int top = mTop + (int) region.top;
+ parent.invalidate(left, top, left + (int) (region.width() + .5f),
+ top + (int) (region.height() + .5f));
+ }
+ }
+ return more;
+ }
+
+ /**
+ * This method is called by ViewGroup.drawChild() to have each child view draw itself.
+ * This draw() method is an implementation detail and is not intended to be overridden or
+ * to be called from anywhere else other than ViewGroup.drawChild().
+ */
+ boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
+ boolean more = false;
+ final boolean childHasIdentityMatrix = hasIdentityMatrix();
+ final int flags = parent.mGroupFlags;
+
+ if ((flags & parent.FLAG_CLEAR_TRANSFORMATION) == parent.FLAG_CLEAR_TRANSFORMATION) {
+ parent.mChildTransformation.clear();
+ parent.mGroupFlags &= ~parent.FLAG_CLEAR_TRANSFORMATION;
+ }
+
+ Transformation transformToApply = null;
+ boolean concatMatrix = false;
+
+ boolean scalingRequired = false;
+ boolean caching;
+ int layerType = parent.mDrawLayers ? getLayerType() : LAYER_TYPE_NONE;
+
+ final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
+ if ((flags & parent.FLAG_CHILDREN_DRAWN_WITH_CACHE) == parent.FLAG_CHILDREN_DRAWN_WITH_CACHE ||
+ (flags & parent.FLAG_ALWAYS_DRAWN_WITH_CACHE) == parent.FLAG_ALWAYS_DRAWN_WITH_CACHE) {
+ caching = true;
+ if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
+ } else {
+ caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
+ }
+
+ final Animation a = getAnimation();
+ if (a != null) {
+ more = drawAnimation(parent, drawingTime, a, scalingRequired);
+ concatMatrix = a.willChangeTransformationMatrix();
+ transformToApply = parent.mChildTransformation;
+ } else if ((flags & parent.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) ==
+ parent.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) {
+ final boolean hasTransform =
+ parent.getChildStaticTransformation(this, parent.mChildTransformation);
+ if (hasTransform) {
+ final int transformType = parent.mChildTransformation.getTransformationType();
+ transformToApply = transformType != Transformation.TYPE_IDENTITY ?
+ parent.mChildTransformation : null;
+ concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
+ }
+ }
+
+ concatMatrix |= !childHasIdentityMatrix;
+
+ // Sets the flag as early as possible to allow draw() implementations
+ // to call invalidate() successfully when doing animations
+ mPrivateFlags |= DRAWN;
+
+ if (!concatMatrix && canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
+ (mPrivateFlags & DRAW_ANIMATION) == 0) {
+ return more;
+ }
+
+ if (hardwareAccelerated) {
+ // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
+ // retain the flag's value temporarily in the mRecreateDisplayList flag
+ mRecreateDisplayList = (mPrivateFlags & INVALIDATED) == INVALIDATED;
+ mPrivateFlags &= ~INVALIDATED;
+ }
+
+ computeScroll();
+
+ final int sx = mScrollX;
+ final int sy = mScrollY;
+
+ DisplayList displayList = null;
+ Bitmap cache = null;
+ boolean hasDisplayList = false;
+ if (caching) {
+ if (!hardwareAccelerated) {
+ if (layerType != LAYER_TYPE_NONE) {
+ layerType = LAYER_TYPE_SOFTWARE;
+ buildDrawingCache(true);
+ }
+ cache = getDrawingCache(true);
+ } else {
+ switch (layerType) {
+ case LAYER_TYPE_SOFTWARE:
+ buildDrawingCache(true);
+ cache = getDrawingCache(true);
+ break;
+ case LAYER_TYPE_NONE:
+ // Delay getting the display list until animation-driven alpha values are
+ // set up and possibly passed on to the view
+ hasDisplayList = canHaveDisplayList();
+ break;
+ }
+ }
+ }
+
+ final boolean hasNoCache = cache == null || hasDisplayList;
+ final boolean offsetForScroll = cache == null && !hasDisplayList &&
+ layerType != LAYER_TYPE_HARDWARE;
+
+ final int restoreTo = canvas.save();
+ if (offsetForScroll) {
+ canvas.translate(mLeft - sx, mTop - sy);
+ } else {
+ canvas.translate(mLeft, mTop);
+ if (scalingRequired) {
+ // mAttachInfo cannot be null, otherwise scalingRequired == false
+ final float scale = 1.0f / mAttachInfo.mApplicationScale;
+ canvas.scale(scale, scale);
+ }
+ }
+
+ float alpha = getAlpha();
+ if (transformToApply != null || alpha < 1.0f || !hasIdentityMatrix()) {
+ if (transformToApply != null || !childHasIdentityMatrix) {
+ int transX = 0;
+ int transY = 0;
+
+ if (offsetForScroll) {
+ transX = -sx;
+ transY = -sy;
+ }
+
+ if (transformToApply != null) {
+ if (concatMatrix) {
+ // Undo the scroll translation, apply the transformation matrix,
+ // then redo the scroll translate to get the correct result.
+ canvas.translate(-transX, -transY);
+ canvas.concat(transformToApply.getMatrix());
+ canvas.translate(transX, transY);
+ parent.mGroupFlags |= parent.FLAG_CLEAR_TRANSFORMATION;
+ }
+
+ float transformAlpha = transformToApply.getAlpha();
+ if (transformAlpha < 1.0f) {
+ alpha *= transformToApply.getAlpha();
+ parent.mGroupFlags |= parent.FLAG_CLEAR_TRANSFORMATION;
+ }
+ }
+
+ if (!childHasIdentityMatrix) {
+ canvas.translate(-transX, -transY);
+ canvas.concat(getMatrix());
+ canvas.translate(transX, transY);
+ }
+ }
+
+ if (alpha < 1.0f) {
+ parent.mGroupFlags |= parent.FLAG_CLEAR_TRANSFORMATION;
+ if (hasNoCache) {
+ final int multipliedAlpha = (int) (255 * alpha);
+ if (!onSetAlpha(multipliedAlpha)) {
+ int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
+ if ((flags & parent.FLAG_CLIP_CHILDREN) == parent.FLAG_CLIP_CHILDREN ||
+ layerType != LAYER_TYPE_NONE) {
+ layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
+ }
+ if (layerType == LAYER_TYPE_NONE) {
+ final int scrollX = hasDisplayList ? 0 : sx;
+ final int scrollY = hasDisplayList ? 0 : sy;
+ canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft,
+ scrollY + mBottom - mTop, multipliedAlpha, layerFlags);
+ }
+ } else {
+ // Alpha is handled by the child directly, clobber the layer's alpha
+ mPrivateFlags |= ALPHA_SET;
+ }
+ }
+ }
+ } else if ((mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
+ onSetAlpha(255);
+ mPrivateFlags &= ~ALPHA_SET;
+ }
+
+ if ((flags & parent.FLAG_CLIP_CHILDREN) == parent.FLAG_CLIP_CHILDREN) {
+ if (offsetForScroll) {
+ canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
+ } else {
+ if (!scalingRequired || cache == null) {
+ canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop);
+ } else {
+ canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
+ }
+ }
+ }
+
+ if (hasDisplayList) {
+ displayList = getDisplayList();
+ if (!displayList.isValid()) {
+ // Uncommon, but possible. If a view is removed from the hierarchy during the call
+ // to getDisplayList(), the display list will be marked invalid and we should not
+ // try to use it again.
+ displayList = null;
+ hasDisplayList = false;
+ }
+ }
+
+ if (hasNoCache) {
+ boolean layerRendered = false;
+ if (layerType == LAYER_TYPE_HARDWARE) {
+ final HardwareLayer layer = getHardwareLayer();
+ if (layer != null && layer.isValid()) {
+ mLayerPaint.setAlpha((int) (alpha * 255));
+ ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
+ layerRendered = true;
+ } else {
+ final int scrollX = hasDisplayList ? 0 : sx;
+ final int scrollY = hasDisplayList ? 0 : sy;
+ canvas.saveLayer(scrollX, scrollY,
+ scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint,
+ Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
+ }
+ }
+
+ if (!layerRendered) {
+ if (!hasDisplayList) {
+ // Fast path for layouts with no backgrounds
+ if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+ if (ViewDebug.TRACE_HIERARCHY) {
+ ViewDebug.trace(parent, ViewDebug.HierarchyTraceType.DRAW);
+ }
+ mPrivateFlags &= ~DIRTY_MASK;
+ dispatchDraw(canvas);
+ } else {
+ draw(canvas);
+ }
+ } else {
+ mPrivateFlags &= ~DIRTY_MASK;
+ ((HardwareCanvas) canvas).drawDisplayList(displayList,
+ mRight - mLeft, mBottom - mTop, null);
+ }
+ }
+ } else if (cache != null) {
+ mPrivateFlags &= ~DIRTY_MASK;
+ Paint cachePaint;
+
+ if (layerType == LAYER_TYPE_NONE) {
+ cachePaint = parent.mCachePaint;
+ if (cachePaint == null) {
+ cachePaint = new Paint();
+ cachePaint.setDither(false);
+ parent.mCachePaint = cachePaint;
+ }
+ if (alpha < 1.0f) {
+ cachePaint.setAlpha((int) (alpha * 255));
+ parent.mGroupFlags |= parent.FLAG_ALPHA_LOWER_THAN_ONE;
+ } else if ((flags & parent.FLAG_ALPHA_LOWER_THAN_ONE) ==
+ parent.FLAG_ALPHA_LOWER_THAN_ONE) {
+ cachePaint.setAlpha(255);
+ parent.mGroupFlags &= ~parent.FLAG_ALPHA_LOWER_THAN_ONE;
+ }
+ } else {
+ cachePaint = mLayerPaint;
+ cachePaint.setAlpha((int) (alpha * 255));
+ }
+ canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
+ }
+
+ canvas.restoreToCount(restoreTo);
+
+ if (a != null && !more) {
+ if (!hardwareAccelerated && !a.getFillAfter()) {
+ onSetAlpha(255);
+ }
+ parent.finishAnimatingView(this, a);
+ }
+
+ if (more && hardwareAccelerated) {
+ // invalidation is the trigger to recreate display lists, so if we're using
+ // display lists to render, force an invalidate to allow the animation to
+ // continue drawing another frame
+ parent.invalidate(true);
+ if (a.hasAlpha() && (mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
+ // alpha animations should cause the child to recreate its display list
+ invalidate(true);
+ }
+ }
+
+ mRecreateDisplayList = false;
+
+ return more;
+ }
+
+ /**
* Manually render this view (and all of its children) to the given Canvas.
* The view must have already done a full layout before this function is
* called. When implementing a view, implement
@@ -13762,7 +14074,6 @@
* {@link #TEXT_DIRECTION_RTL},
* {@link #TEXT_DIRECTION_LOCALE},
*
- * @hide
*/
public int getTextDirection() {
return mTextDirection;
@@ -13780,7 +14091,6 @@
* {@link #TEXT_DIRECTION_RTL},
* {@link #TEXT_DIRECTION_LOCALE},
*
- * @hide
*/
public void setTextDirection(int textDirection) {
if (textDirection != mTextDirection) {
@@ -13801,7 +14111,6 @@
* {@link #TEXT_DIRECTION_RTL},
* {@link #TEXT_DIRECTION_LOCALE},
*
- * @hide
*/
public int getResolvedTextDirection() {
if (mResolvedTextDirection == TEXT_DIRECTION_INHERIT) {
@@ -13813,7 +14122,6 @@
/**
* Resolve the text direction.
*
- * @hide
*/
protected void resolveTextDirection() {
if (mTextDirection != TEXT_DIRECTION_INHERIT) {
@@ -13830,7 +14138,6 @@
/**
* Reset resolved text direction. Will be resolved during a call to getResolvedTextDirection().
*
- * @hide
*/
protected void resetResolvedTextDirection() {
mResolvedTextDirection = TEXT_DIRECTION_INHERIT;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index d3af618..bc147ac 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -103,18 +103,18 @@
* A Transformation used when drawing children, to
* apply on the child being drawn.
*/
- private final Transformation mChildTransformation = new Transformation();
+ final Transformation mChildTransformation = new Transformation();
/**
* Used to track the current invalidation region.
*/
- private RectF mInvalidateRegion;
+ RectF mInvalidateRegion;
/**
* A Transformation used to calculate a correct
* invalidation area when the application is autoscaled.
*/
- private Transformation mInvalidationTransformation;
+ Transformation mInvalidationTransformation;
// View currently under an ongoing drag
private View mCurrentDragView;
@@ -170,7 +170,7 @@
// When set, ViewGroup invalidates only the child's rectangle
// Set by default
- private static final int FLAG_CLIP_CHILDREN = 0x1;
+ static final int FLAG_CLIP_CHILDREN = 0x1;
// When set, ViewGroup excludes the padding area from the invalidate rectangle
// Set by default
@@ -178,7 +178,7 @@
// When set, dispatchDraw() will invoke invalidate(); this is set by drawChild() when
// a child needs to be invalidated and FLAG_OPTIMIZE_INVALIDATE is set
- private static final int FLAG_INVALIDATE_REQUIRED = 0x4;
+ static final int FLAG_INVALIDATE_REQUIRED = 0x4;
// When set, dispatchDraw() will run the layout animation and unset the flag
private static final int FLAG_RUN_ANIMATION = 0x8;
@@ -186,7 +186,7 @@
// When set, there is either no layout animation on the ViewGroup or the layout
// animation is over
// Set by default
- private static final int FLAG_ANIMATION_DONE = 0x10;
+ static final int FLAG_ANIMATION_DONE = 0x10;
// If set, this ViewGroup has padding; if unset there is no padding and we don't need
// to clip it, even if FLAG_CLIP_TO_PADDING is set
@@ -200,10 +200,10 @@
// layout animation; this avoid clobbering the hierarchy
// Automatically set when the layout animation starts, depending on the animation's
// characteristics
- private static final int FLAG_OPTIMIZE_INVALIDATE = 0x80;
+ static final int FLAG_OPTIMIZE_INVALIDATE = 0x80;
// When set, the next call to drawChild() will clear mChildTransformation's matrix
- private static final int FLAG_CLEAR_TRANSFORMATION = 0x100;
+ static final int FLAG_CLEAR_TRANSFORMATION = 0x100;
// When set, this ViewGroup invokes mAnimationListener.onAnimationEnd() and removes
// the children's Bitmap caches if necessary
@@ -233,7 +233,7 @@
// When the previous drawChild() invocation used an alpha value that was lower than
// 1.0 and set it in mCachePaint
- private static final int FLAG_ALPHA_LOWER_THAN_ONE = 0x1000;
+ static final int FLAG_ALPHA_LOWER_THAN_ONE = 0x1000;
/**
* When set, this ViewGroup's drawable states also include those
@@ -244,13 +244,13 @@
/**
* When set, this ViewGroup tries to always draw its children using their drawing cache.
*/
- private static final int FLAG_ALWAYS_DRAWN_WITH_CACHE = 0x4000;
+ static final int FLAG_ALWAYS_DRAWN_WITH_CACHE = 0x4000;
/**
* When set, and if FLAG_ALWAYS_DRAWN_WITH_CACHE is not set, this ViewGroup will try to
* draw its children with their drawing cache.
*/
- private static final int FLAG_CHILDREN_DRAWN_WITH_CACHE = 0x8000;
+ static final int FLAG_CHILDREN_DRAWN_WITH_CACHE = 0x8000;
/**
* When set, this group will go through its list of children to notify them of
@@ -352,7 +352,7 @@
private static final int ARRAY_CAPACITY_INCREMENT = 12;
// Used to draw cached views
- private Paint mCachePaint;
+ Paint mCachePaint;
// Used to animate add/remove changes in layout
private LayoutTransition mTransition;
@@ -368,7 +368,7 @@
// Indicates whether this container will use its children layers to draw
@ViewDebug.ExportedProperty(category = "drawing")
- private boolean mDrawLayers = true;
+ boolean mDrawLayers = true;
public ViewGroup(Context context) {
super(context);
@@ -675,14 +675,11 @@
*/
@Override
public void clearFocus() {
- if (DBG) {
- System.out.println(this + " clearFocus()");
- }
- if (mFocused == null) {
- super.clearFocus();
- } else {
+ super.clearFocus();
+
+ // clear any child focus if it exists
+ if (mFocused != null) {
mFocused.clearFocus();
- mFocused = null;
}
}
@@ -694,12 +691,12 @@
if (DBG) {
System.out.println(this + " unFocus()");
}
- if (mFocused == null) {
- super.unFocus();
- } else {
+
+ super.unFocus();
+ if (mFocused != null) {
mFocused.unFocus();
- mFocused = null;
}
+ mFocused = null;
}
/**
@@ -2620,336 +2617,11 @@
*
* @param canvas The canvas on which to draw the child
* @param child Who to draw
- * @param drawingTime The time at which draw is occuring
+ * @param drawingTime The time at which draw is occurring
* @return True if an invalidate() was issued
*/
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
- boolean more = false;
-
- final int cl = child.mLeft;
- final int ct = child.mTop;
- final int cr = child.mRight;
- final int cb = child.mBottom;
-
- final boolean childHasIdentityMatrix = child.hasIdentityMatrix();
-
- final int flags = mGroupFlags;
-
- if ((flags & FLAG_CLEAR_TRANSFORMATION) == FLAG_CLEAR_TRANSFORMATION) {
- mChildTransformation.clear();
- mGroupFlags &= ~FLAG_CLEAR_TRANSFORMATION;
- }
-
- Transformation transformToApply = null;
- Transformation invalidationTransform;
- final Animation a = child.getAnimation();
- boolean concatMatrix = false;
-
- boolean scalingRequired = false;
- boolean caching;
- int layerType = mDrawLayers ? child.getLayerType() : LAYER_TYPE_NONE;
-
- final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
- if ((flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE ||
- (flags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE) {
- caching = true;
- if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
- } else {
- caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
- }
-
- if (a != null) {
- final boolean initialized = a.isInitialized();
- if (!initialized) {
- a.initialize(cr - cl, cb - ct, getWidth(), getHeight());
- a.initializeInvalidateRegion(0, 0, cr - cl, cb - ct);
- child.onAnimationStart();
- }
-
- more = a.getTransformation(drawingTime, mChildTransformation, 1f);
- if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
- if (mInvalidationTransformation == null) {
- mInvalidationTransformation = new Transformation();
- }
- invalidationTransform = mInvalidationTransformation;
- a.getTransformation(drawingTime, invalidationTransform, 1f);
- } else {
- invalidationTransform = mChildTransformation;
- }
- transformToApply = mChildTransformation;
-
- concatMatrix = a.willChangeTransformationMatrix();
-
- if (more) {
- if (!a.willChangeBounds()) {
- if ((flags & (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE)) ==
- FLAG_OPTIMIZE_INVALIDATE) {
- mGroupFlags |= FLAG_INVALIDATE_REQUIRED;
- } else if ((flags & FLAG_INVALIDATE_REQUIRED) == 0) {
- // The child need to draw an animation, potentially offscreen, so
- // make sure we do not cancel invalidate requests
- mPrivateFlags |= DRAW_ANIMATION;
- invalidate(cl, ct, cr, cb);
- }
- } else {
- if (mInvalidateRegion == null) {
- mInvalidateRegion = new RectF();
- }
- final RectF region = mInvalidateRegion;
- a.getInvalidateRegion(0, 0, cr - cl, cb - ct, region, invalidationTransform);
-
- // The child need to draw an animation, potentially offscreen, so
- // make sure we do not cancel invalidate requests
- mPrivateFlags |= DRAW_ANIMATION;
-
- final int left = cl + (int) region.left;
- final int top = ct + (int) region.top;
- invalidate(left, top, left + (int) (region.width() + .5f),
- top + (int) (region.height() + .5f));
- }
- }
- } else if ((flags & FLAG_SUPPORT_STATIC_TRANSFORMATIONS) ==
- FLAG_SUPPORT_STATIC_TRANSFORMATIONS) {
- final boolean hasTransform = getChildStaticTransformation(child, mChildTransformation);
- if (hasTransform) {
- final int transformType = mChildTransformation.getTransformationType();
- transformToApply = transformType != Transformation.TYPE_IDENTITY ?
- mChildTransformation : null;
- concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
- }
- }
-
- concatMatrix |= !childHasIdentityMatrix;
-
- // Sets the flag as early as possible to allow draw() implementations
- // to call invalidate() successfully when doing animations
- child.mPrivateFlags |= DRAWN;
-
- if (!concatMatrix && canvas.quickReject(cl, ct, cr, cb, Canvas.EdgeType.BW) &&
- (child.mPrivateFlags & DRAW_ANIMATION) == 0) {
- return more;
- }
-
- if (hardwareAccelerated) {
- // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
- // retain the flag's value temporarily in the mRecreateDisplayList flag
- child.mRecreateDisplayList = (child.mPrivateFlags & INVALIDATED) == INVALIDATED;
- child.mPrivateFlags &= ~INVALIDATED;
- }
-
- child.computeScroll();
-
- final int sx = child.mScrollX;
- final int sy = child.mScrollY;
-
- DisplayList displayList = null;
- Bitmap cache = null;
- boolean hasDisplayList = false;
- if (caching) {
- if (!hardwareAccelerated) {
- if (layerType != LAYER_TYPE_NONE) {
- layerType = LAYER_TYPE_SOFTWARE;
- child.buildDrawingCache(true);
- }
- cache = child.getDrawingCache(true);
- } else {
- switch (layerType) {
- case LAYER_TYPE_SOFTWARE:
- child.buildDrawingCache(true);
- cache = child.getDrawingCache(true);
- break;
- case LAYER_TYPE_NONE:
- // Delay getting the display list until animation-driven alpha values are
- // set up and possibly passed on to the view
- hasDisplayList = child.canHaveDisplayList();
- break;
- }
- }
- }
-
- final boolean hasNoCache = cache == null || hasDisplayList;
- final boolean offsetForScroll = cache == null && !hasDisplayList &&
- layerType != LAYER_TYPE_HARDWARE;
-
- final int restoreTo = canvas.save();
- if (offsetForScroll) {
- canvas.translate(cl - sx, ct - sy);
- } else {
- canvas.translate(cl, ct);
- if (scalingRequired) {
- // mAttachInfo cannot be null, otherwise scalingRequired == false
- final float scale = 1.0f / mAttachInfo.mApplicationScale;
- canvas.scale(scale, scale);
- }
- }
-
- float alpha = child.getAlpha();
- if (transformToApply != null || alpha < 1.0f || !child.hasIdentityMatrix()) {
- if (transformToApply != null || !childHasIdentityMatrix) {
- int transX = 0;
- int transY = 0;
-
- if (offsetForScroll) {
- transX = -sx;
- transY = -sy;
- }
-
- if (transformToApply != null) {
- if (concatMatrix) {
- // Undo the scroll translation, apply the transformation matrix,
- // then redo the scroll translate to get the correct result.
- canvas.translate(-transX, -transY);
- canvas.concat(transformToApply.getMatrix());
- canvas.translate(transX, transY);
- mGroupFlags |= FLAG_CLEAR_TRANSFORMATION;
- }
-
- float transformAlpha = transformToApply.getAlpha();
- if (transformAlpha < 1.0f) {
- alpha *= transformToApply.getAlpha();
- mGroupFlags |= FLAG_CLEAR_TRANSFORMATION;
- }
- }
-
- if (!childHasIdentityMatrix) {
- canvas.translate(-transX, -transY);
- canvas.concat(child.getMatrix());
- canvas.translate(transX, transY);
- }
- }
-
- if (alpha < 1.0f) {
- mGroupFlags |= FLAG_CLEAR_TRANSFORMATION;
- if (hasNoCache) {
- final int multipliedAlpha = (int) (255 * alpha);
- if (!child.onSetAlpha(multipliedAlpha)) {
- int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
- if ((flags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN ||
- layerType != LAYER_TYPE_NONE) {
- layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
- }
- if (layerType == LAYER_TYPE_NONE) {
- final int scrollX = hasDisplayList ? 0 : sx;
- final int scrollY = hasDisplayList ? 0 : sy;
- canvas.saveLayerAlpha(scrollX, scrollY, scrollX + cr - cl,
- scrollY + cb - ct, multipliedAlpha, layerFlags);
- }
- } else {
- // Alpha is handled by the child directly, clobber the layer's alpha
- child.mPrivateFlags |= ALPHA_SET;
- }
- }
- }
- } else if ((child.mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
- child.onSetAlpha(255);
- child.mPrivateFlags &= ~ALPHA_SET;
- }
-
- if ((flags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {
- if (offsetForScroll) {
- canvas.clipRect(sx, sy, sx + (cr - cl), sy + (cb - ct));
- } else {
- if (!scalingRequired || cache == null) {
- canvas.clipRect(0, 0, cr - cl, cb - ct);
- } else {
- canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
- }
- }
- }
-
- if (hasDisplayList) {
- displayList = child.getDisplayList();
- if (!displayList.isValid()) {
- // Uncommon, but possible. If a view is removed from the hierarchy during the call
- // to getDisplayList(), the display list will be marked invalid and we should not
- // try to use it again.
- displayList = null;
- hasDisplayList = false;
- }
- }
-
- if (hasNoCache) {
- boolean layerRendered = false;
- if (layerType == LAYER_TYPE_HARDWARE) {
- final HardwareLayer layer = child.getHardwareLayer();
- if (layer != null && layer.isValid()) {
- child.mLayerPaint.setAlpha((int) (alpha * 255));
- ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, child.mLayerPaint);
- layerRendered = true;
- } else {
- final int scrollX = hasDisplayList ? 0 : sx;
- final int scrollY = hasDisplayList ? 0 : sy;
- canvas.saveLayer(scrollX, scrollY,
- scrollX + cr - cl, scrollY + cb - ct, child.mLayerPaint,
- Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
- }
- }
-
- if (!layerRendered) {
- if (!hasDisplayList) {
- // Fast path for layouts with no backgrounds
- if ((child.mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
- if (ViewDebug.TRACE_HIERARCHY) {
- ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
- }
- child.mPrivateFlags &= ~DIRTY_MASK;
- child.dispatchDraw(canvas);
- } else {
- child.draw(canvas);
- }
- } else {
- child.mPrivateFlags &= ~DIRTY_MASK;
- ((HardwareCanvas) canvas).drawDisplayList(displayList, cr - cl, cb - ct, null);
- }
- }
- } else if (cache != null) {
- child.mPrivateFlags &= ~DIRTY_MASK;
- Paint cachePaint;
-
- if (layerType == LAYER_TYPE_NONE) {
- cachePaint = mCachePaint;
- if (cachePaint == null) {
- cachePaint = new Paint();
- cachePaint.setDither(false);
- mCachePaint = cachePaint;
- }
- if (alpha < 1.0f) {
- cachePaint.setAlpha((int) (alpha * 255));
- mGroupFlags |= FLAG_ALPHA_LOWER_THAN_ONE;
- } else if ((flags & FLAG_ALPHA_LOWER_THAN_ONE) == FLAG_ALPHA_LOWER_THAN_ONE) {
- cachePaint.setAlpha(255);
- mGroupFlags &= ~FLAG_ALPHA_LOWER_THAN_ONE;
- }
- } else {
- cachePaint = child.mLayerPaint;
- cachePaint.setAlpha((int) (alpha * 255));
- }
- canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
- }
-
- canvas.restoreToCount(restoreTo);
-
- if (a != null && !more) {
- if (!hardwareAccelerated && !a.getFillAfter()) {
- child.onSetAlpha(255);
- }
- finishAnimatingView(child, a);
- }
-
- if (more && hardwareAccelerated) {
- // invalidation is the trigger to recreate display lists, so if we're using
- // display lists to render, force an invalidate to allow the animation to
- // continue drawing another frame
- invalidate(true);
- if (a.hasAlpha() && (child.mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
- // alpha animations should cause the child to recreate its display list
- child.invalidate(true);
- }
- }
-
- child.mRecreateDisplayList = false;
-
- return more;
+ return child.draw(canvas, this, drawingTime);
}
/**
@@ -4854,7 +4526,7 @@
* @param view The view whose animation has finished
* @param animation The animation, cannot be null
*/
- private void finishAnimatingView(final View view, Animation animation) {
+ void finishAnimatingView(final View view, Animation animation) {
final ArrayList<View> disappearingChildren = mDisappearingChildren;
if (disappearingChildren != null) {
if (disappearingChildren.contains(view)) {
@@ -5203,6 +4875,10 @@
return true;
}
+ /** @hide */
+ protected void onSetLayoutParams(View child, LayoutParams layoutParams) {
+ }
+
/**
* LayoutParams are used by views to tell their parents how they want to be
* laid out. See
@@ -5411,29 +5087,33 @@
*/
public static class MarginLayoutParams extends ViewGroup.LayoutParams {
/**
- * The left margin in pixels of the child. Whenever this value is changed, a call to
- * {@link android.view.View#requestLayout()} needs to be done.
+ * The left margin in pixels of the child.
+ * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value
+ * to this field.
*/
@ViewDebug.ExportedProperty(category = "layout")
public int leftMargin;
/**
- * The top margin in pixels of the child. Whenever this value is changed, a call to
- * {@link android.view.View#requestLayout()} needs to be done.
+ * The top margin in pixels of the child.
+ * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value
+ * to this field.
*/
@ViewDebug.ExportedProperty(category = "layout")
public int topMargin;
/**
- * The right margin in pixels of the child. Whenever this value is changed, a call to
- * {@link android.view.View#requestLayout()} needs to be done.
+ * The right margin in pixels of the child.
+ * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value
+ * to this field.
*/
@ViewDebug.ExportedProperty(category = "layout")
public int rightMargin;
/**
- * The bottom margin in pixels of the child. Whenever this value is changed, a call to
- * {@link android.view.View#requestLayout()} needs to be done.
+ * The bottom margin in pixels of the child.
+ * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value
+ * to this field.
*/
@ViewDebug.ExportedProperty(category = "layout")
public int bottomMargin;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 1930a5e..1c3bbfa 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -174,7 +174,6 @@
View mView;
View mFocusedView;
View mRealFocusedView; // this is not set to null in touch mode
- View mOldFocusedView;
int mViewVisibility;
boolean mAppVisible = true;
int mOrigWindowType = -1;
@@ -2273,34 +2272,33 @@
public void requestChildFocus(View child, View focused) {
checkThread();
-
- if (DEBUG_INPUT_RESIZE) {
- Log.v(TAG, "Request child focus: focus now " + focused);
+ if (mFocusedView != focused) {
+ mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(mFocusedView, focused);
+ scheduleTraversals();
}
-
- mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(mOldFocusedView, focused);
- scheduleTraversals();
-
mFocusedView = mRealFocusedView = focused;
+ if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Request child focus: focus now "
+ + mFocusedView);
}
public void clearChildFocus(View child) {
checkThread();
- if (DEBUG_INPUT_RESIZE) {
- Log.v(TAG, "Clearing child focus");
- }
+ View oldFocus = mFocusedView;
- mOldFocusedView = mFocusedView;
-
- // Invoke the listener only if there is no view to take focus
- if (focusSearch(null, View.FOCUS_FORWARD) == null) {
- mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(mOldFocusedView, null);
- }
-
+ if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Clearing child focus");
mFocusedView = mRealFocusedView = null;
+ if (mView != null && !mView.hasFocus()) {
+ // If a view gets the focus, the listener will be invoked from requestChildFocus()
+ if (!mView.requestFocus(View.FOCUS_FORWARD)) {
+ mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
+ }
+ } else if (oldFocus != null) {
+ mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
+ }
}
+
public void focusableViewAvailable(View v) {
checkThread();
@@ -2772,7 +2770,6 @@
mView.unFocus();
mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(focused, null);
mFocusedView = null;
- mOldFocusedView = null;
return true;
}
}
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 6bdc4e8..6dbdedb 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -480,9 +480,19 @@
try {
synchronized (this) {
if (mViews != null) {
- pw.println("View hierarchy:");
-
final int count = mViews.length;
+
+ pw.println("Profile data in ms:");
+
+ for (int i = 0; i < count; i++) {
+ ViewRootImpl root = mRoots[i];
+ HardwareRenderer renderer = root.getView().mAttachInfo.mHardwareRenderer;
+ if (renderer != null) {
+ renderer.dumpGfxInfo(pw);
+ }
+ }
+
+ pw.println("\nView hierarchy:");
int viewsCount = 0;
int displayListsSize = 0;
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index fbafc64..332a0eb 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -4803,7 +4803,9 @@
if (layer == 0 || isPictureAfterFirstLayout) {
mWebViewCore.resumeWebKitDraw();
} else if (queueFull) {
- mWebViewCore.pauseWebKitDraw();
+ // temporarily disable webkit draw throttling
+ // TODO: re-enable
+ // mWebViewCore.pauseWebKitDraw();
}
if (mHTML5VideoViewProxy != null) {
@@ -6111,7 +6113,7 @@
calcOurContentVisibleRectF(mVisibleContentRect);
nativeUpdateDrawGLFunction(mGLViewportEmpty ? null : mGLRectViewport,
mGLViewportEmpty ? null : mViewRectViewport,
- mVisibleContentRect);
+ mVisibleContentRect, getScale());
}
/**
@@ -9885,7 +9887,7 @@
private native int nativeGetDrawGLFunction(int nativeInstance, Rect rect,
Rect viewRect, RectF visibleRect, float scale, int extras);
private native void nativeUpdateDrawGLFunction(Rect rect, Rect viewRect,
- RectF visibleRect);
+ RectF visibleRect, float scale);
private native void nativeExtendSelection(int x, int y);
private native int nativeFindAll(String findLower, String findUpper,
boolean sameAsLastSearch);
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index ae2d617..369e883 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -258,6 +258,7 @@
// Remember the current zoom density before it gets changed.
final float originalDefault = mDefaultScale;
// set the new default density
+ mDisplayDensity = density;
setDefaultZoomScale(density);
float scaleChange = (originalDefault > 0.0) ? density / originalDefault: 1.0f;
// adjust the scale if it falls outside the new zoom bounds
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 984ec79..ea40dc2 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -212,6 +212,7 @@
static final int PRF = 1;
static final int MAX_SIZE = 100000;
static final int DEFAULT_CONTAINER_MARGIN = 0;
+ static final int UNINITIALIZED_HASH = 0;
// Defaults
@@ -240,6 +241,7 @@
boolean useDefaultMargins = DEFAULT_USE_DEFAULT_MARGINS;
int alignmentMode = DEFAULT_ALIGNMENT_MODE;
int defaultGap;
+ int lastLayoutParamsHashCode = UNINITIALIZED_HASH;
// Constructors
@@ -566,6 +568,10 @@
return FILL;
case AXIS_SPECIFIED:
return CENTER;
+ case (AXIS_SPECIFIED | AXIS_PULL_BEFORE | RELATIVE_LAYOUT_DIRECTION):
+ return START;
+ case (AXIS_SPECIFIED | AXIS_PULL_AFTER | RELATIVE_LAYOUT_DIRECTION):
+ return END;
default:
return UNDEFINED_ALIGNMENT;
}
@@ -590,7 +596,8 @@
Spec spec = horizontal ? p.columnSpec : p.rowSpec;
Axis axis = horizontal ? horizontalAxis : verticalAxis;
Interval span = spec.span;
- boolean isAtEdge = leading ? (span.min == 0) : (span.max == axis.getCount());
+ boolean leading1 = (horizontal && isLayoutRtl()) ? !leading : leading;
+ boolean isAtEdge = leading1 ? (span.min == 0) : (span.max == axis.getCount());
return getDefaultMargin(c, isAtEdge, horizontal, leading);
}
@@ -663,7 +670,7 @@
int[] maxSizes = new int[count];
for (int i = 0, N = getChildCount(); i < N; i++) {
- LayoutParams lp = getLayoutParams1(getChildAt(i));
+ LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams();
final Spec majorSpec = horizontal ? lp.rowSpec : lp.columnSpec;
final Interval majorRange = majorSpec.span;
@@ -708,6 +715,7 @@
minor = minor + minorSpan;
}
+ lastLayoutParamsHashCode = computeLayoutParamsHashCode();
invalidateStructure();
}
@@ -728,8 +736,11 @@
}
}
- private LayoutParams getLayoutParams1(View c) {
- return (LayoutParams) c.getLayoutParams();
+ /** @hide */
+ @Override
+ protected void onSetLayoutParams(View child, ViewGroup.LayoutParams layoutParams) {
+ super.onSetLayoutParams(child, layoutParams);
+ invalidateStructure();
}
final LayoutParams getLayoutParams(View c) {
@@ -737,7 +748,7 @@
validateLayoutParams();
layoutParamsValid = true;
}
- return getLayoutParams1(c);
+ return (LayoutParams) c.getLayoutParams();
}
@Override
@@ -760,10 +771,15 @@
private void drawLine(Canvas graphics, int x1, int y1, int x2, int y2, Paint paint) {
int dx = getPaddingLeft();
int dy = getPaddingTop();
- graphics.drawLine(dx + x1, dy + y1, dx + x2, dy + y2, paint);
+ if (isLayoutRtl()) {
+ int width = getWidth();
+ graphics.drawLine(width - dx - x1, dy + y1, width - dx - x2, dy + y2, paint);
+ } else {
+ graphics.drawLine(dx + x1, dy + y1, dx + x2, dy + y2, paint);
+ }
}
- private static void drawRect(Canvas canvas, int x1, int y1, int x2, int y2, Paint paint) {
+ private void drawRect(Canvas canvas, int x1, int y1, int x2, int y2, Paint paint) {
canvas.drawRect(x1, y1, x2 - 1, y2 - 1, paint);
}
@@ -849,12 +865,29 @@
}
}
- // Measurement
-
- final boolean isGone(View c) {
- return c.getVisibility() == View.GONE;
+ private int computeLayoutParamsHashCode() {
+ int result = 1;
+ for (int i = 0, N = getChildCount(); i < N; i++) {
+ View c = getChildAt(i);
+ if (c.getVisibility() == View.GONE) continue;
+ LayoutParams lp = (LayoutParams) c.getLayoutParams();
+ result = 31 * result + lp.hashCode();
+ }
+ return result;
}
+ private void checkForLayoutParamsModification() {
+ int layoutParamsHashCode = computeLayoutParamsHashCode();
+ if (lastLayoutParamsHashCode != UNINITIALIZED_HASH &&
+ lastLayoutParamsHashCode != layoutParamsHashCode) {
+ invalidateStructure();
+ Log.w(TAG, "The fields of some layout parameters were modified in between layout " +
+ "operations. Check the javadoc for GridLayout.LayoutParams#rowSpec.");
+ }
+ }
+
+ // Measurement
+
private void measureChildWithMargins2(View child, int parentWidthSpec, int parentHeightSpec,
int childWidth, int childHeight) {
int childWidthSpec = getChildMeasureSpec(parentWidthSpec,
@@ -867,7 +900,7 @@
private void measureChildrenWithMargins(int widthSpec, int heightSpec, boolean firstPass) {
for (int i = 0, N = getChildCount(); i < N; i++) {
View c = getChildAt(i);
- if (isGone(c)) continue;
+ if (c.getVisibility() == View.GONE) continue;
LayoutParams lp = getLayoutParams(c);
if (firstPass) {
measureChildWithMargins2(c, widthSpec, heightSpec, lp.width, lp.height);
@@ -892,6 +925,8 @@
@Override
protected void onMeasure(int widthSpec, int heightSpec) {
+ checkForLayoutParamsModification();
+
/** If we have been called by {@link View#measure(int, int)}, one of width or height
* is likely to have changed. We must invalidate if so. */
invalidateValues();
@@ -931,7 +966,7 @@
}
final int getMeasurementIncludingMargin(View c, boolean horizontal) {
- if (isGone(c)) {
+ if (c.getVisibility() == View.GONE) {
return 0;
}
return getMeasurement(c, horizontal) + getTotalMargin(c, horizontal);
@@ -945,7 +980,7 @@
final Alignment getAlignment(Alignment alignment, boolean horizontal) {
return (alignment != UNDEFINED_ALIGNMENT) ? alignment :
- (horizontal ? LEFT : BASELINE);
+ (horizontal ? START : BASELINE);
}
// Layout container
@@ -964,6 +999,8 @@
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ checkForLayoutParamsModification();
+
int targetWidth = right - left;
int targetHeight = bottom - top;
@@ -980,7 +1017,7 @@
for (int i = 0, N = getChildCount(); i < N; i++) {
View c = getChildAt(i);
- if (isGone(c)) continue;
+ if (c.getVisibility() == View.GONE) continue;
LayoutParams lp = getLayoutParams(c);
Spec columnSpec = lp.columnSpec;
Spec rowSpec = lp.rowSpec;
@@ -1003,41 +1040,41 @@
Alignment hAlign = getAlignment(columnSpec.alignment, true);
Alignment vAlign = getAlignment(rowSpec.alignment, false);
- int dx, dy;
-
Bounds colBounds = horizontalAxis.getGroupBounds().getValue(i);
Bounds rowBounds = verticalAxis.getGroupBounds().getValue(i);
// Gravity offsets: the location of the alignment group relative to its cell group.
//noinspection NullableProblems
- int c2ax = protect(hAlign.getAlignmentValue(null, cellWidth - colBounds.size(true)));
+ int gravityOffsetX = protect(hAlign.getAlignmentValue(null,
+ cellWidth - colBounds.size(true)));
//noinspection NullableProblems
- int c2ay = protect(vAlign.getAlignmentValue(null, cellHeight - rowBounds.size(true)));
+ int gravityOffsetY = protect(vAlign.getAlignmentValue(null,
+ cellHeight - rowBounds.size(true)));
- int leftMargin = getMargin(c, true, true);
+ boolean rtl = isLayoutRtl();
+ int startMargin = getMargin(c, true, !rtl);
int topMargin = getMargin(c, false, true);
- int rightMargin = getMargin(c, true, false);
+ int endMargin = getMargin(c, true, rtl);
int bottomMargin = getMargin(c, false, false);
// Same calculation as getMeasurementIncludingMargin()
- int mWidth = leftMargin + pWidth + rightMargin;
+ int mWidth = startMargin + pWidth + endMargin;
int mHeight = topMargin + pHeight + bottomMargin;
// Alignment offsets: the location of the view relative to its alignment group.
- int a2vx = colBounds.getOffset(c, hAlign, mWidth);
- int a2vy = rowBounds.getOffset(c, vAlign, mHeight);
+ int alignmentOffsetX = colBounds.getOffset(c, hAlign, mWidth);
+ int alignmentOffsetY = rowBounds.getOffset(c, vAlign, mHeight);
- dx = c2ax + a2vx + leftMargin;
- dy = c2ay + a2vy + topMargin;
+ int dx = gravityOffsetX + alignmentOffsetX + startMargin;
+ int dy = gravityOffsetY + alignmentOffsetY + topMargin;
- cellWidth -= leftMargin + rightMargin;
+ cellWidth -= startMargin + endMargin;
cellHeight -= topMargin + bottomMargin;
- int type = PRF;
- int width = hAlign.getSizeInCell(c, pWidth, cellWidth, type);
- int height = vAlign.getSizeInCell(c, pHeight, cellHeight, type);
+ int width = hAlign.getSizeInCell(c, pWidth, cellWidth, PRF);
+ int height = vAlign.getSizeInCell(c, pHeight, cellHeight, PRF);
- int cx = paddingLeft + x1 + dx;
+ int cx = rtl ? targetWidth - paddingRight - x1 - dx - width : paddingLeft + x1 + dx;
int cy = paddingTop + y1 + dy;
if (width != c.getMeasuredWidth() || height != c.getMeasuredHeight()) {
c.measure(makeMeasureSpec(width, EXACTLY), makeMeasureSpec(height, EXACTLY));
@@ -1517,7 +1554,7 @@
int[] margins = leading ? leadingMargins : trailingMargins;
for (int i = 0, N = getChildCount(); i < N; i++) {
View c = getChildAt(i);
- if (isGone(c)) continue;
+ if (c.getVisibility() == View.GONE) continue;
LayoutParams lp = getLayoutParams(c);
Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
Interval span = spec.span;
@@ -1757,12 +1794,28 @@
/**
* The spec that defines the vertical characteristics of the cell group
* described by these layout parameters.
+ * If an assignment is made to this field after a measurement or layout operation
+ * has already taken place, a call to
+ * {@link ViewGroup#setLayoutParams(ViewGroup.LayoutParams)}
+ * must be made to notify GridLayout of the change. GridLayout is normally able
+ * to detect when code fails to observe this rule, issue a warning and take steps to
+ * compensate for the omission. This facility is implemented on a best effort basis
+ * and should not be relied upon in production code - so it is best to include the above
+ * calls to remove the warnings as soon as it is practical.
*/
public Spec rowSpec = Spec.UNDEFINED;
/**
* The spec that defines the horizontal characteristics of the cell group
* described by these layout parameters.
+ * If an assignment is made to this field after a measurement or layout operation
+ * has already taken place, a call to
+ * {@link ViewGroup#setLayoutParams(ViewGroup.LayoutParams)}
+ * must be made to notify GridLayout of the change. GridLayout is normally able
+ * to detect when code fails to observe this rule, issue a warning and take steps to
+ * compensate for the omission. This facility is implemented on a best effort basis
+ * and should not be relied upon in production code - so it is best to include the above
+ * calls to remove the warnings as soon as it is practical.
*/
public Spec columnSpec = Spec.UNDEFINED;
@@ -1907,6 +1960,26 @@
final void setColumnSpecSpan(Interval span) {
columnSpec = columnSpec.copyWriteSpan(span);
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ LayoutParams that = (LayoutParams) o;
+
+ if (!columnSpec.equals(that.columnSpec)) return false;
+ if (!rowSpec.equals(that.rowSpec)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = rowSpec.hashCode();
+ result = 31 * result + columnSpec.hashCode();
+ return result;
+ }
}
/*
@@ -2049,7 +2122,7 @@
/*
For each group (with a given alignment) we need to store the amount of space required
before the alignment point and the amount of space required after it. One side of this
- calculation is always 0 for LEADING and TRAILING alignments but we don't make use of this.
+ calculation is always 0 for START and END alignments but we don't make use of this.
For CENTER and BASELINE alignments both sides are needed and in the BASELINE case no
simple optimisations are possible.
@@ -2405,18 +2478,29 @@
}
static final Alignment UNDEFINED_ALIGNMENT = new Alignment() {
+ @Override
public int getAlignmentValue(View view, int viewSize) {
return UNDEFINED;
}
};
+ /**
+ * Indicates that a view should be aligned with the <em>start</em>
+ * edges of the other views in its cell group.
+ */
private static final Alignment LEADING = new Alignment() {
+ @Override
public int getAlignmentValue(View view, int viewSize) {
return 0;
}
};
+ /**
+ * Indicates that a view should be aligned with the <em>end</em>
+ * edges of the other views in its cell group.
+ */
private static final Alignment TRAILING = new Alignment() {
+ @Override
public int getAlignmentValue(View view, int viewSize) {
return viewSize;
}
@@ -2435,16 +2519,41 @@
public static final Alignment BOTTOM = TRAILING;
/**
- * Indicates that a view should be aligned with the <em>right</em>
+ * Indicates that a view should be aligned with the <em>start</em>
* edges of the other views in its cell group.
*/
- public static final Alignment RIGHT = TRAILING;
+ public static final Alignment START = LEADING;
+
+ /**
+ * Indicates that a view should be aligned with the <em>end</em>
+ * edges of the other views in its cell group.
+ */
+ public static final Alignment END = TRAILING;
+
+ private static Alignment getAbsoluteAlignment(final Alignment a1, final Alignment a2) {
+ return new Alignment() {
+ @Override
+ public int getAlignmentValue(View view, int viewSize) {
+ if (view == null) {
+ return UNDEFINED;
+ }
+ Alignment alignment = view.isLayoutRtl() ? a2 : a1;
+ return alignment.getAlignmentValue(view, viewSize);
+ }
+ };
+ }
/**
* Indicates that a view should be aligned with the <em>left</em>
* edges of the other views in its cell group.
*/
- public static final Alignment LEFT = LEADING;
+ public static final Alignment LEFT = getAbsoluteAlignment(START, END);
+
+ /**
+ * Indicates that a view should be aligned with the <em>right</em>
+ * edges of the other views in its cell group.
+ */
+ public static final Alignment RIGHT = getAbsoluteAlignment(END, START);
/**
* Indicates that a view should be <em>centered</em> with the other views in its cell group.
@@ -2452,6 +2561,7 @@
* LayoutParams#columnSpec columnSpecs}.
*/
public static final Alignment CENTER = new Alignment() {
+ @Override
public int getAlignmentValue(View view, int viewSize) {
return viewSize >> 1;
}
@@ -2465,6 +2575,7 @@
* @see View#getBaseline()
*/
public static final Alignment BASELINE = new Alignment() {
+ @Override
public int getAlignmentValue(View view, int viewSize) {
if (view == null) {
return UNDEFINED;
@@ -2515,6 +2626,7 @@
* {@link LayoutParams#columnSpec columnSpecs}.
*/
public static final Alignment FILL = new Alignment() {
+ @Override
public int getAlignmentValue(View view, int viewSize) {
return UNDEFINED;
}
@@ -2530,6 +2642,5 @@
}
private static final int INFLEXIBLE = 0;
-
private static final int CAN_STRETCH = 2;
}
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 570f0f9..909f383 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -426,7 +426,8 @@
}
// A new word has been created across the interval boundaries with this edit.
- // Previous spans (ended on start / started on end) removed, not valid anymore
+ // The previous spans (that ended on start / started on end) are not valid
+ // anymore and must be removed.
if (wordStart < start && wordEnd > start) {
removeSpansAt(editable, start, spellCheckSpans);
removeSpansAt(editable, start, suggestionSpans);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 99349b0..7db8a1e 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3472,6 +3472,9 @@
if (mText.length() == 0) {
invalidate();
}
+
+ // Invalidate display list if hint will be used
+ if (mText.length() == 0 && mHint != null) mTextDisplayListIsValid = false;
}
/**
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 547607e..68a8de8 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -220,7 +220,7 @@
ALOGE("Error creating AudioRecord: Error retrieving session id pointer");
goto native_init_failure;
}
- // read the audio session ID back from AudioTrack in case a new session was created during set()
+ // read the audio session ID back from AudioRecord in case a new session was created during set()
nSession[0] = lpRecorder->getSessionId();
env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
nSession = NULL;
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 31c5ed4..ee5eb7e 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -1,4 +1,4 @@
-/* //device/libs/android_runtime/android_media_AudioSystem.cpp
+/*
**
** Copyright 2006, The Android Open Source Project
**
diff --git a/core/jni/android_media_ToneGenerator.cpp b/core/jni/android_media_ToneGenerator.cpp
index 0a337fa..544b4c0 100644
--- a/core/jni/android_media_ToneGenerator.cpp
+++ b/core/jni/android_media_ToneGenerator.cpp
@@ -1,4 +1,4 @@
-/* //device/libs/android_runtime/android_media_AudioSystem.cpp
+/*
**
** Copyright 2008, The Android Open Source Project
**
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index 2ac3ca8..c5ff16e 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -116,14 +116,9 @@
return (jboolean)(::wifi_unload_driver() == 0);
}
-static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject)
+static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject, jboolean p2pSupported)
{
- return (jboolean)(::wifi_start_supplicant() == 0);
-}
-
-static jboolean android_net_wifi_startP2pSupplicant(JNIEnv* env, jobject)
-{
- return (jboolean)(::wifi_start_p2p_supplicant() == 0);
+ return (jboolean)(::wifi_start_supplicant(p2pSupported) == 0);
}
static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject)
@@ -207,8 +202,7 @@
{ "loadDriver", "()Z", (void *)android_net_wifi_loadDriver },
{ "isDriverLoaded", "()Z", (void *)android_net_wifi_isDriverLoaded },
{ "unloadDriver", "()Z", (void *)android_net_wifi_unloadDriver },
- { "startSupplicant", "()Z", (void *)android_net_wifi_startSupplicant },
- { "startP2pSupplicant", "()Z", (void *)android_net_wifi_startP2pSupplicant },
+ { "startSupplicant", "(Z)Z", (void *)android_net_wifi_startSupplicant },
{ "killSupplicant", "()Z", (void *)android_net_wifi_killSupplicant },
{ "connectToSupplicant", "(Ljava/lang/String;)Z",
(void *)android_net_wifi_connectToSupplicant },
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index bba4b47..18bcea1 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -572,7 +572,7 @@
}
static jobject Surface_screenshot(JNIEnv* env, jobject clazz, jint width, jint height,
- jint minLayer, jint maxLayer, bool allLayers)
+ jint minLayer, jint maxLayer)
{
return doScreenshot(env, clazz, width, height, minLayer, maxLayer, false);
}
diff --git a/core/res/res/anim/recents_fade_in.xml b/core/res/res/anim/recents_fade_in.xml
new file mode 100644
index 0000000..c516fadb
--- /dev/null
+++ b/core/res/res/anim/recents_fade_in.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/anim/recents_fade_in.xml
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@interpolator/decelerate_quad"
+ android:fromAlpha="0.0" android:toAlpha="1.0"
+ android:duration="150" />
diff --git a/core/res/res/anim/recents_fade_out.xml b/core/res/res/anim/recents_fade_out.xml
new file mode 100644
index 0000000..7468cc19
--- /dev/null
+++ b/core/res/res/anim/recents_fade_out.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/anim/recents_fade_out.xml
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@interpolator/accelerate_quad"
+ android:fromAlpha="1.0"
+ android:toAlpha="0.0"
+ android:duration="150" />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 96c125c..19398cf 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -543,30 +543,30 @@
<item msgid="1735177144948329370">"Tuisfaks"</item>
<item msgid="603878674477207394">"Roeper"</item>
<item msgid="1650824275177931637">"Ander"</item>
- <item msgid="9192514806975898961">"Gepasmaakte"</item>
+ <item msgid="9192514806975898961">"Gepasmaak"</item>
</string-array>
<string-array name="emailAddressTypes">
<item msgid="8073994352956129127">"Tuis"</item>
<item msgid="7084237356602625604">"Werk"</item>
<item msgid="1112044410659011023">"Ander"</item>
- <item msgid="2374913952870110618">"Gepasmaakte"</item>
+ <item msgid="2374913952870110618">"Gepasmaak"</item>
</string-array>
<string-array name="postalAddressTypes">
<item msgid="6880257626740047286">"Tuis"</item>
<item msgid="5629153956045109251">"Werk"</item>
<item msgid="4966604264500343469">"Ander"</item>
- <item msgid="4932682847595299369">"Gepasmaakte"</item>
+ <item msgid="4932682847595299369">"Gepasmaak"</item>
</string-array>
<string-array name="imAddressTypes">
<item msgid="1738585194601476694">"Tuis"</item>
<item msgid="1359644565647383708">"Werk"</item>
<item msgid="7868549401053615677">"Ander"</item>
- <item msgid="3145118944639869809">"Gepasmaakte"</item>
+ <item msgid="3145118944639869809">"Gepasmaak"</item>
</string-array>
<string-array name="organizationTypes">
<item msgid="7546335612189115615">"Werk"</item>
<item msgid="4378074129049520373">"Ander"</item>
- <item msgid="3455047468583965104">"Gepasmaakte"</item>
+ <item msgid="3455047468583965104">"Gepasmaak"</item>
</string-array>
<string-array name="imProtocols">
<item msgid="8595261363518459565">"AIM"</item>
@@ -578,7 +578,7 @@
<item msgid="2506857312718630823">"ICQ"</item>
<item msgid="1648797903785279353">"Jabber"</item>
</string-array>
- <string name="phoneTypeCustom" msgid="1644738059053355820">"Gepasmaakte"</string>
+ <string name="phoneTypeCustom" msgid="1644738059053355820">"Gepasmaak"</string>
<string name="phoneTypeHome" msgid="2570923463033985887">"Tuis"</string>
<string name="phoneTypeMobile" msgid="6501463557754751037">"Mobiel"</string>
<string name="phoneTypeWork" msgid="8863939667059911633">"Werk"</string>
@@ -599,24 +599,24 @@
<string name="phoneTypeWorkPager" msgid="649938731231157056">"Werkroeper"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"Assistent"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
- <string name="eventTypeCustom" msgid="7837586198458073404">"Gepasmaakte"</string>
+ <string name="eventTypeCustom" msgid="7837586198458073404">"Gepasmaak"</string>
<string name="eventTypeBirthday" msgid="2813379844211390740">"Verjaardag"</string>
<string name="eventTypeAnniversary" msgid="3876779744518284000">"Herdenking"</string>
<string name="eventTypeOther" msgid="7388178939010143077">"Ander"</string>
- <string name="emailTypeCustom" msgid="8525960257804213846">"Gepasmaakte"</string>
+ <string name="emailTypeCustom" msgid="8525960257804213846">"Gepasmaak"</string>
<string name="emailTypeHome" msgid="449227236140433919">"Tuis"</string>
<string name="emailTypeWork" msgid="3548058059601149973">"Werk"</string>
<string name="emailTypeOther" msgid="2923008695272639549">"Ander"</string>
<string name="emailTypeMobile" msgid="119919005321166205">"Mobiel"</string>
- <string name="postalTypeCustom" msgid="8903206903060479902">"Gepasmaakte"</string>
+ <string name="postalTypeCustom" msgid="8903206903060479902">"Gepasmaak"</string>
<string name="postalTypeHome" msgid="8165756977184483097">"Tuis"</string>
<string name="postalTypeWork" msgid="5268172772387694495">"Werk"</string>
<string name="postalTypeOther" msgid="2726111966623584341">"Ander"</string>
- <string name="imTypeCustom" msgid="2074028755527826046">"Gepasmaakte"</string>
+ <string name="imTypeCustom" msgid="2074028755527826046">"Gepasmaak"</string>
<string name="imTypeHome" msgid="6241181032954263892">"Tuis"</string>
<string name="imTypeWork" msgid="1371489290242433090">"Werk"</string>
<string name="imTypeOther" msgid="5377007495735915478">"Ander"</string>
- <string name="imProtocolCustom" msgid="6919453836618749992">"Gepasmaakte"</string>
+ <string name="imProtocolCustom" msgid="6919453836618749992">"Gepasmaak"</string>
<string name="imProtocolAim" msgid="7050360612368383417">"AIM"</string>
<string name="imProtocolMsn" msgid="144556545420769442">"Windows Live"</string>
<string name="imProtocolYahoo" msgid="8271439408469021273">"Yahoo"</string>
@@ -628,8 +628,8 @@
<string name="imProtocolNetMeeting" msgid="8287625655986827971">"NetMeeting"</string>
<string name="orgTypeWork" msgid="29268870505363872">"Werk"</string>
<string name="orgTypeOther" msgid="3951781131570124082">"Ander"</string>
- <string name="orgTypeCustom" msgid="225523415372088322">"Gepasmaakte"</string>
- <string name="relationTypeCustom" msgid="3542403679827297300">"Gepasmaakte"</string>
+ <string name="orgTypeCustom" msgid="225523415372088322">"Gepasmaak"</string>
+ <string name="relationTypeCustom" msgid="3542403679827297300">"Gepasmaak"</string>
<string name="relationTypeAssistant" msgid="6274334825195379076">"Assistent"</string>
<string name="relationTypeBrother" msgid="8757913506784067713">"Broer"</string>
<string name="relationTypeChild" msgid="1890746277276881626">"Kind"</string>
@@ -644,7 +644,7 @@
<string name="relationTypeRelative" msgid="1799819930085610271">"Familielid"</string>
<string name="relationTypeSister" msgid="1735983554479076481">"Suster"</string>
<string name="relationTypeSpouse" msgid="394136939428698117">"Eggenoot"</string>
- <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Gepasmaakte"</string>
+ <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Gepasmaak"</string>
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Tuis"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Werk"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Ander"</string>
@@ -764,6 +764,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Laat die program toe om te verifieer dat \'n pakket installeerbaar is."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"bind aan \'n pakkieverifieerder"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Laat die houer toe om versoeke aan pakketverifieerders te rig. Dit moet nooit vir normale programme nodig wees nie."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"kry toegang tot reekspoorte"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Laat die houer toe om toegang te verkry tot reekspoorte wat die SerialManager API gebruik."</string>
<string name="save_password_message" msgid="767344687139195790">"Wil jy hê die blaaier moet hierdie wagwoord onthou?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Nie nou nie"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Onthou"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 52b690d..8f7b70f 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"ወደ ግንባር ዎይ እና ዳራ ስራዎችን ለማንቀሳቀስ ለመተግበሪያው ይፈቅዳሉ፡፡ ያለአንተ ቁጥጥር ተንኮል አዘል መተግበሪያዎች ራሳቸውን ወደፊት መምጣት ሊያስገድዱ ይችላሉ፡፡"</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"የአሂድ ትግበራዎች አቁም"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"ተግባሮችን ለማስወገድ እና መተግበሪያዎቻቸውን ለመግደል ለመተግበሪያ ይፈቅዳል። ጎጂ የሆኑ መተግበሪያዎች የሌሎችን መተግበሪያዎችን ባህሪ ሊያውኩ ይችላሉ።"</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"የማያ ገጽ ተኳኋኝነት መድብ"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"መተግበሪያው የሌሎች መተግበሪያዎች የማያ ገጽ ተኳኋኝነት ሁናቴ እንዲቆጣጠር ይፈቅዳል። ተንኮለኛ መተግበሪያዎች የሌሎች መተግበሪያዎች ባህሪ ሊሰብሩ ይችላሉ።"</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"የትግበራ ማረሚያ አንቃ"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"ለሌላ መተግበሪያ አርምን አብራ ለመተግበሪያው ይፈቅዳሉ። ሌሎች መተግበሪያዎች ለመግደል ተንኮል አዘል መተግበሪያዎች ይሄንን ሊጠቀሙት ይችላሉ።"</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"የUI ቅንብሮችን ለውጥ"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"ፓኬጅ መጫን የሚችል መሆኑን ለማረጋገጥ ለመተግበሪያው ይፈቅዳሉ፡፡"</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"በፓኬጅ አረጋጋጭ የተወሰነ"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"የፓኬጅ አረጋጋጮችን ጥየቃ ለማድረግ ያዡ ይፈቅዳሉ። ለመደበኛ ትግበራዎች በፍፁም አያስፈልግም።"</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"ተከታታይ ወደቦችን ድረስ"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Allows the holder to access serial ports using the SerialManager API. የተከታታይ አደራጅ APIን በመጠቀም ያዡ የተከታታይ ወደቦችን እንዲደርስ ይፈቅዳል።"</string>
<string name="save_password_message" msgid="767344687139195790">"አሳሹ ይህን ይለፍ ቃል እንዲያስታወስ ይፈልጋሉ?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"አሁን አይደለም"</string>
<string name="save_password_remember" msgid="6491879678996749466">"አስታውስ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 2c02f66..c9de7de 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"للسماح لتطبيق ما بنقل المهام إلى المقدمة والخلفية. قد تفرض التطبيقات الضارة نفسها إلى المقدمة بدون تحكم منك."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"إيقاف التطبيقات التي قيد التشغيل"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"للسماح للتطبيق بإزالة المهام وإنهاء تطبيقاتها. قد تعطل التطبيقات الضارة عمل التطبيقات الأخرى."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"تعيين توافق الشاشة"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"السماح للتطبيق بالتحكم في وضع التوافق مع شاشة التطبيقات الأخرى. قد تتسبب التطبيقات الضارة في تعطيل سلوك التطبيقات الأخرى."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"تمكين تصحيح أخطاء التطبيق"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"للسماح للتطبيق بتشغيل تصحيح الأخطاء لتطبيق آخر. قد تستخدم التطبيقات الضارة هذا لإنهاء التطبيقات الأخرى."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"تغيير إعدادات واجهة المستخدم"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"السماح للتطبيق بالتحقق من إمكانية تثبيت حزمة."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"الالتزام بمحقق حزمة"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"السماح للمالك بإجراء طلبات محققي الحزمة. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"الدخول إلى المنافذ التسلسلية"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"يسمح لحامله بالدخول إلى المنافذ التسلسلية باستخدام واجهة برمجة التطبيقات."</string>
<string name="save_password_message" msgid="767344687139195790">"هل تريد من المتصفح تذكر كلمة المرور هذه؟"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"ليس الآن"</string>
<string name="save_password_remember" msgid="6491879678996749466">"تذكّر"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index d17447e6..adb1338 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Дазваляе прыкладанням перамяшчаць заданні на пярэдні план і фон. Шкоднасныя прыкладанні могуць прымусова рабіць сябе асноўнымі без вашага ведама."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"спыніць запушчаныя прыкладанні"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Дазваляе прыкладанням выдаляць заданні і спыняць прыкладанні, якія іх выкарыстоўваюць. Шкоднасныя прыкладаннi могуць перашкодзiць працы іншых прыкладанняў."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"усталяваць сумяшчальнасць экранаў"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Дазваляе прыкладанню кіраваць рэжымам сумяшчальнасці экранаў іншых прыкладанняў. Шкоднаснае ПЗ можа перашкодзiць працы іншых прыкладанняў."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"уключыць адладку прыкладання"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Дазваляе прыкладанням уключаць адладку для іншага прыкладання. Шкоднасныя прыкладанні могуць выкарыстоўваць гэта, каб спыняць іншыя прыкладанні."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"змяняць налады карыстальніцкага інтэрфейса"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Дазваляе прыкладанням правяраць магчымасць усталявання пакету."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"прывязаць да верыфікатару пакету"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Дазваляе ўладальніку рабіць запыты верыфікатараў пакету. Не патрабуецца для звычайных прыкладанняў."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"атрымаць доступ да паслядоўных партоў"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Дазваляе ўладальніку атрымліваць доступ да паслядоўных партоў з дапамогай API SerialManager."</string>
<string name="save_password_message" msgid="767344687139195790">"Вы хочаце, каб браўзэр запомніў гэты пароль?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Не цяпер"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Запомніць"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 5c54a60..0a22133 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Разрешава на приложението да прехвърля задачи на преден и на заден план. Злонамерените приложения могат сами да се изведат на преден план без ваша намеса."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"спиране на изпълняваните приложения"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Разрешава на приложението да премахва задачи и да прекратява приложенията им. Злонамерените приложения могат да нарушат поведението на други приложения."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"задаване на съвместимост на екрана"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Разрешава на приложението да контролира режима на съвместимост на екрана на други приложения. Злонамерените програми могат да нарушат поведението на други приложения."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"активиране на отстраняването на грешки в приложения"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Разрешава на приложението да включва отстраняването на грешки за друго приложение. Злонамерените приложения могат да използват това, за да прекратят други приложения."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"промяна на настройките ви за потребителския интерфейс"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Разрешава на приложението да провери дали пакетът може да се инсталира."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"обвързване с верификатор на пакета"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Разрешава на притежателя да прави заявки за верификатори на пакета. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"достъп до серийни портове"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Разрешава на притежателя достъп до серийни портове посредством приложния програмен интерфейс (API) SerialManager."</string>
<string name="save_password_message" msgid="767344687139195790">"Искате ли браузърът да запомни тази парола?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Не сега"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Запомняне"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 6faa7ff..460fcb7 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Permet que l\'aplicació desplaci tasques en primer o segon pla. Les aplicacions malicioses poden aparèixer en primer pla sense el teu consentiment."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"atura les aplicacions que s\'estan executant"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Permet que l\'aplicació elimini tasques i finalitzi les seves aplicacions. Les aplicacions malicioses poden alterar el comportament d\'altres aplicacions."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"definició de la compatibilitat de pantalla"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Permet que l\'aplicació controli el mode de compatibilitat de pantalla d\'altres aplicacions. És possible que les aplicacions malicioses interrompin el comportament d\'altres aplicacions."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"activa la depuració d\'aplicacions"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Permet que una aplicació activi la depuració per a una altra aplicació. Les aplicacions malicioses poden utilitzar aquesta funció per finalitzar altres aplicacions."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"canviar la configuració de la IU"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Permet que l\'aplicació verifiqui si un paquet es pot instal·lar."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"vincula a un verificador de paquets"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Permet que el titular sol·liciti verificadors de paquets. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"accedeix a ports sèrie"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Permet que el titular accedeixi a ports sèrie amb l\'API SerialManager."</string>
<string name="save_password_message" msgid="767344687139195790">"Voleu que el navegador recordi aquesta contrasenya?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Ara no"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Recorda-ho"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index d0cdd0d..545d957 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Umožňuje aplikaci přesunout úlohy na popředí nebo pozadí. Škodlivé aplikace mohou vynutit zobrazení na popředí bez vašeho svolení."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"zastavení činnosti aplikací"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Umožňuje aplikaci odstranit úlohy a ukončit jejich aplikace. Škodlivé aplikace mohou narušit chování ostatních aplikací."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"nastavit kompatibilitu obrazovky"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Umožňuje aplikaci ovládat režim kompatibility obrazovky v ostatních aplikacích. Škodlivé aplikace mohou narušit chování ostatních aplikací."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"povolení ladění aplikací"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Umožňuje aplikaci zapnout ladění jiné aplikace. Škodlivé aplikace mohou toto oprávnění použít k ukončení ostatních aplikací."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"změna vašeho nastavení uživatelského rozhraní"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Umožňuje aplikaci ověřit, zda balíček lze nainstalovat."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"navázat na ověřovatele balíčků"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Umožňuje držiteli podávat žádosti o ověření balíčků. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"přístup k sériovým portům"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Umožňuje držiteli přístup k sériovým portům pomocí rozhraní SerialManager API."</string>
<string name="save_password_message" msgid="767344687139195790">"Chcete, aby si prohlížeč zapamatoval toto heslo?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Nyní ne"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Zapamatovat"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 44a7707..65d7cdc 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Tillader, at appen kan flytte opgaver til forgrunden og baggrunden. Ondsindede apps kan tvinge sig selv i forgrunden uden din kontrol."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"stoppe kørsel af apps"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Tillader, at en app kan fjerne opgaver og lukke deres apps. Ondsindede apps kan forstyrre adfærden for andre apps."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"indstil skærmens kompatibilitet"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Tillader, at appen kontrollerer kompatibilitetstilstanden for skærme i andre applikationer. Ondsindede applikationer kan forstyrre andre applikationers adfærd."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"aktivere fejlretning af appen"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Tillader, at appen kan slå fejlretning til for en anden app. Ondsindede apps kan bruge dette til at afslutte andre apps."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"skift indstillinger for brugergrænsefladen"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Tillader, at appen kan bekræfte, at en pakke kan installeres."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"bind til en bekræftelse af pakker"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Tillader, at indehaveren kan sende anmodninger om bekræftelser af pakker. Dette bør aldrig være nødvendigt for almindelige apps."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"adgang til serielle porte"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Tillader, at indehaveren kan få adgang til serielle porte ved hjælp af SerialManager API."</string>
<string name="save_password_message" msgid="767344687139195790">"Ønsker du, at browseren skal huske denne adgangskode?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Ikke nu"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Husk"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 7d0ce02..dbe8137 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Ermöglicht der App, Aufgaben in den Vorder- und Hintergrund zu verschieben. Schädliche Apps können so ohne Ihr Zutun eine Anzeige im Vordergrund erzwingen."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"Aktive Apps beenden"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Ermöglicht der App, Aufgaben zu entfernen und die entsprechenden Apps zu beenden. Schädliche Apps können das Verhalten anderer Apps stören."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"Bildschirmkompatibilität festlegen"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Ermöglicht der App, den Bildschirmkompatibilitätsmodus anderer Apps zu steuern. Schädliche Apps können das Verhalten anderer Apps stören."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"Fehlerbeseitigung für App aktivieren"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Ermöglicht der App, die Fehlerbeseitigung für eine andere App zu aktivieren. Schädliche Apps können so andere Apps beenden."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"UI-Einstellungen ändern"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Ermöglicht der App die Überprüfung, ob ein Paket installiert werden kann"</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"An Paketprüfung binden"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Ermöglicht dem Halter, Anfragen für die Paketprüfung zu senden. Sollte nie für normale Apps benötigt werden."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"Zugriff auf serielle Schnittstellen"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Ermöglicht dem Inhaber den Zugriff auf serielle Schnittstellen über das SerialManager-API"</string>
<string name="save_password_message" msgid="767344687139195790">"Möchten Sie, dass der Browser dieses Passwort speichert?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Nicht jetzt"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Speichern"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 49465e8..154ca55 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -764,6 +764,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Επιτρέπει στην εφαρμογή να επαληθεύσει τη δυνατότητα εγκατάστασης ενός πακέτου."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"δέσμευση με επαλήθευση πακέτου"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Επιτρέπει στον κάτοχο να υποβάλλει ερωτήματα σε προγράμματα επαλήθευσης πακέτου. Δεν απαιτείται για συνήθεις εφαρμογές."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"πρόσβαση στις σειριακές θύρες"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Επιτρέπει στον κάτοχο την πρόσβαση στις σειριακές θύρες με τη χρήση του SerialManager API."</string>
<string name="save_password_message" msgid="767344687139195790">"Θέλετε το πρόγραμμα περιήγησης να διατηρήσει αυτόν τον κωδικό πρόσβασης;"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Να μην γίνει τώρα"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Διατήρηση"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 33a3b7a..0429c8b 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Allows the app to move tasks to the foreground and background. Malicious apps may force themselves to the front without your control."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"stop running apps"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Allows the app to remove tasks and kill their apps. Malicious apps may disrupt the behaviour of other apps."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"set screen compatibility"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Allows the app to control the screen compatibility mode of other applications. Malicious applications may break the behaviour of other applications."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"enable app debugging"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Allows the app to turn on debugging for another app. Malicious apps may use this to kill other apps."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"change your UI settings"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Allows the app to verify a package is installable."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"bind to a package verifier"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Allows the holder to make requests of package verifiers. Should never be needed for normal apps."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"access serial ports"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Allows the holder to access serial ports using the SerialManager API."</string>
<string name="save_password_message" msgid="767344687139195790">"Do you want the browser to remember this password?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Not now"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Remember"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 41d2a47..ad3e949 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Permite que la aplicación mueva tareas al primero o segundo plano. Las aplicaciones maliciosas pueden forzar su paso al primer plano sin que tú las controles."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"detener las aplicaciones en ejecución"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Permite que la aplicación elimine tareas y cierre sus aplicaciones. Las aplicaciones malintencionadas pueden usar este permiso para interferir en el comportamiento de otras aplicaciones."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"Configurar el modo de la compatibilidad de otras pantalla"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Permite a la aplicación controlar el modo de la compatibilidad de las pantallas de otras aplicaciones. Las aplicaciones malintencionadas pueden interrumpir el funcionamiento de otras aplicaciones."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"activar depuración de aplicación"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Permite que la aplicación active la depuración de otra aplicación. Las aplicaciones malintencionadas pueden usar este permiso para interrumpir la ejecución de otras aplicaciones."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"cambiar tu configuración de la interfaz de usuario"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Permite que la aplicación verifique si se puede instalar un paquete."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"Vincular a un verificador de paquetes"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Permite que el titular solicite verificadores de paquetes. Las aplicaciones normales no deberían necesitar este permiso."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"Acceder a los puertos serie"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Permite acceder a puertos serie a través de la API SerialManager."</string>
<string name="save_password_message" msgid="767344687139195790">"¿Quieres recordar esta contraseña en el navegador?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Ahora no."</string>
<string name="save_password_remember" msgid="6491879678996749466">"Recuerda"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index e9b1ab3..1bd13bd 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Permite que la aplicación mueva tareas a segundo o a primer plano. Algunas aplicaciones malintencionadas pueden aparecer en primer plano sin el control del usuario."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"detener aplicaciones en ejecución"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Permite que la aplicación termine tareas y cierre sus aplicaciones. Las aplicaciones malintencionadas pueden usar este permiso para interferir en el comportamiento de otras aplicaciones."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"establecer compatibilidad de pantalla"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Permite que la aplicación controle el modo de compatibilidad de la pantalla de otras aplicaciones. Las aplicaciones malintencionadas pueden influir de forma negativa en el funcionamiento de otras aplicaciones."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"habilitar depuración de aplicación"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Permite que la aplicación active la depuración de otra aplicación. Las aplicaciones malintencionadas pueden usar este permiso para interrumpir la ejecución de otras aplicaciones."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"cambiar la configuración de la interfaz de usuario"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Permite que la aplicación verifique si se puede instalar un paquete."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"enlazar con un detector de paquetes"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Permite que se envíen solicitudes de detectores de paquetes. Las aplicaciones normales no deberían necesitar este permiso."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"acceder a puertos serie"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Permite acceder a puertos serie a través de SerialManager API."</string>
<string name="save_password_message" msgid="767344687139195790">"¿Quieres que el navegador recuerde esta contraseña?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Ahora no"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Recordar"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 8dfebb6..2f42a70 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Võimaldab rakendusel teisaldada ülesanded esiplaanile ja taustale. Pahatahtlikud rakendused võivad sundida end esiplaanile tulema teie loata."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"käitatud rakenduste peatamine"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Võimaldab rakendusel eemaldada ülesanded ja peatada nende rakendused. Pahatahtlikud rakendused võivad häirida teiste rakenduste käitumist."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"kuva ühilduvuse seadmine"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Võimaldab rakendusel juhtida teiste rakenduste kuva ühilduvuse režiimi. Pahatahtlikud rakendused võivad teisi rakendusi häirida."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"Rakenduse silumise lubamine"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Võimaldab rakendusel lülitada sisse teise rakenduse silumise. Pahatahtlikud rakendused võivad seda kasutada teiste rakenduste peatamiseks."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"muuda UI-seadeid"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Võimaldab rakendusel kinnitada, et paketti saab installida."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"sidumine paketi kinnitajaga"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Lubab omanikul teha taotlusi paketi kinnitajate kohta. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"juurdepääs jadaportidele"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Võimaldab omanikul SerialManageri API-liidese abil jadaportidele juurde pääseda."</string>
<string name="save_password_message" msgid="767344687139195790">"Kas soovite, et brauser jätaks selle parooli meelde?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Mitte praegu"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Pidage meeles"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index a5bf61a..fd7a771 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"به برنامه اجازه میدهد تا کارها را به پیش زمینه و پس زمینه منتقل کند. برنامههای مخرب میتوانند بدون کنترل به اجبار خود را به جلو منتقل کنند."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"متوقف کردن برنامههای در حال اجرا"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"به برنامه اجازه میدهد تا کارها را حذف کند و برنامههای آنها را متوقف کند. برنامههای مخرب میتوانند در اجرای برنامههای دیگر اختلال ایجاد کنند."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"تنظیم سازگاری با صفحه نمایش"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"به برنامه کاربردی اجازه کنترل حالت سازگاری صفحه نمایش برای برنامههای دیگر را میدهد. برنامههای خرابکار ممکن است باعث کارکرد نادرست دیگر برنامهها شوند."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"فعال کردن عیبیابی برنامه"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"به برنامه اجازه میدهد تا عیبیابی را برای برنامهای دیگر فعال کند. برنامههای مخرب میتوانند از آن استفاده کنند تا اجرای برنامههای دیگر را متوقف کنند."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"تغییر تنظیمات UI"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"به برنامه اجازه میدهد قابل نصب بودن بسته را تأیید کند."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"اتصال به یک تأیید کننده بسته"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"به دارنده اجازه میدهد تا تاییدکنندگان بسته را درخواست کند. برای برنامههای عادی نیاز نیست."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"دسترسی به درگاههای سریال"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"به دارنده اجازه میدهد با استفاده از SerialManager API به درگاههای سریال دسترسی داشته باشد."</string>
<string name="save_password_message" msgid="767344687139195790">"می خواهید مرورگر این رمز ورود را به خاطر داشته باشد؟"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"اکنون خیر"</string>
<string name="save_password_remember" msgid="6491879678996749466">"به خاطر سپردن"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 801f815..9cf18ec 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Antaa sovelluksen siirtää tehtäviä etualalle ja taustalle. Haitalliset sovellukset voivat pakottaa itsensä etualalle ilman käyttäjän hallintaa."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"käynnissä olevien sovellusten pysäyttäminen"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Antaa sovelluksen poistaa tehtäviä ja lopettaa niiden sovelluksia. Haitalliset sovellukset voivat häiritä muiden sovellusten toimintaa."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"aseta näytön yhteensopivuus"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Sallii sovelluksen hallita toisten sovellusten näytön yhteensopivuustilaa. Haittasovellukset voivat häiritä toisten sovellusten toimintaa."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"sovellusten vianetsinnän käyttöönotto"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Antaa sovelluksen ottaa vianetsinnän käyttöön toisessa sovelluksessa. Haitalliset ohjelmat voivat lopettaa tällä muita sovelluksia."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"muuta käyttöliittymäsi asetuksia"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Antaa sovelluksen vahvistaa, että pakkaus on asennettavissa."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"sitoudu paketin vahvistajaan"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Antaa sovelluksen tehdä pakettien vahvistuspyyntöjä. Ei tavallisten sovellusten käyttöön."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"käytä sarjaportteja"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Luvan haltija voi käyttää sarjaportteja SerialManager-sovellusliittymän avulla."</string>
<string name="save_password_message" msgid="767344687139195790">"Haluatko selaimen muistavan tämän salasanan?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Ei nyt"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Muista"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 2848cd5..33b0f45 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Permet à l\'application de faire passer les tâches de premier plan en arrière-plan. Des applications malveillantes peuvent exploiter cette fonctionnalité pour passer au premier plan sans votre consentement."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"arrêter les applications en cours d\'exécution"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Permet à l\'application de supprimer des tâches et de fermer les applications qui les exécutent. Des applications malveillantes peuvent exploiter cette fonctionnalité pour perturber le comportement des autres applications."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"définir la compatibilité de l\'écran"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Permettre de contrôler le mode de compatibilité de l\'écran des autres applications. Des applications malveillantes peuvent perturber le fonctionnement d\'autres applications."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"activer le débogage des applications"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Permet à l\'application d\'activer le débogage d\'une autre application. Des applications malveillantes peuvent exploiter cette fonctionnalité pour en fermer d\'autres."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"Modification des paramètres de l\'IU"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Permet à l\'application de vérifier qu\'un package peut être installé."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"associer à un vérificateur de package"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Permet à l\'application autorisée d\'effectuer des requêtes de vérificateurs de package. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"accéder aux ports série"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Permet à l\'application autorisée d\'accéder aux ports série avec l\'API SerialManager."</string>
<string name="save_password_message" msgid="767344687139195790">"Voulez-vous que le navigateur se souvienne de ce mot de passe ?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Pas maintenant"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Mémoriser"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index f56871a..91ac5a3 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"एप्लिकेशन को अग्रभूमि और पृष्ठभूमि में कार्यों को ले जाने देता है. दुर्भावनापूर्ण एप्लिकेशन आपके नियंत्रण के बिना स्वयं को बलपूर्वक आगे कर सकते हैं."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"चलने वाले एप्लिकेशन रोकें"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"किसी एप्लिकेशन को कार्यों को निकालने और उनके एप्लिकेशन समाप्त करने देता है. दुर्भावनापूर्ण एप्लिकेशन अन्य एप्लिकेशन का व्यवहार बाधित कर सकते हैं."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"स्क्रीन संगतता सेट करें"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"एप्लिकेशन को अन्य एप्लिकेशन के स्क्रीन संगतता मोड को नियंत्रित करने देता है. दुर्भावनापूर्ण एप्लिकेशन अन्य एप्लिकेशन का व्यवहार बाधित कर सकते हैं."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"एप्लिकेशन डीबग करना सक्षम करें"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"एप्लिकेशन को अन्य एप्लिकेशन के लिए डीबग किया जाना चालू करने देता है. दुर्भावनापूर्ण एप्लिकेशन इसका उपयोग अन्य एप्लिकेशन को समाप्त करने के लिए कर सकते हैं."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"अपनी UI सेटिंग बदलें"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"एप्लिकेशन को इंस्टॉल करने योग्य पैकेज सत्यापित करने देता है."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"पैकेज प्रमाणक से आबद्ध करें"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"धारक को पैकेज प्रमाणक के अनुरोध की अनुमति देता है. सामान्य एप्लिकेशन के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"सीरियल पोर्ट पर पहुंचें"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"SerialManager API का उपयोग करके धारक को सीरियल पोर्ट पर पहुंच प्रदान करता है."</string>
<string name="save_password_message" msgid="767344687139195790">"क्या आप चाहते हैं कि ब्राउज़र पासवर्ड को याद रखे?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"अभी नहीं"</string>
<string name="save_password_remember" msgid="6491879678996749466">"याद रखें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 7c4a9d7..a60dcfa 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Omogućuje aplikaciji da premjesti zadatke u prednji plan ili pozadinu. Zlonamjerne aplikacije mogu na silu doći u prednji plan bez vašeg nadzora."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"zaustavljanje pokrenutih aplikacija"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Omogućuje aplikaciji uklanjanje zadataka i uklanjanje njihovih aplikacija. Zlonamjerne aplikacije mogu poremetiti rad drugih aplikacija."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"postavljanje zaslona kompatibilnost"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Aplikaciji omogućuje upravljanje načinom kompatibilnosti zaslona drugih aplikacija. Zlonamjerne aplikacije mogu prekinuti takvo ponašanje ostalih aplikacija."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"omogućavanje rješavanja programskih pogrešaka u aplikaciji"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Omogućuje aplikaciji uključivanje uklanjanja programskih pogrešaka za drugu aplikaciju. Zlonamjerne aplikacije mogu na taj način ukloniti druge aplikacije."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"promjena postavki korisničkog sučelja"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Aplikaciji omogućuje da provjeri je li paket moguće instalirati."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"vezano uz paketnu provjeru"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Nositelju omogućuje da traži paketnu provjeru. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"pristup serijskim priključcima"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Rukovatelju omogućuje pristup serijskim priključcima pomoću značajke SerialManager API."</string>
<string name="save_password_message" msgid="767344687139195790">"Želite li da preglednik zapamti ovu zaporku?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Ne sada"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Zapamti"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index e8920bc..6b789ea 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Lehetővé teszi az alkalmazás számára, hogy feladatokat helyezzen át az előtérből a háttérbe és fordítva. A rosszindulatú alkalmazások az előtérbe helyezhetik magukat az Ön engedélye nélkül."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"futó alkalmazások leállítása"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Lehetővé teszi, hogy az alkalmazás feladatokat távolítson el és leállítsa azok alkalmazásait. Rosszindulatú alkalmazások megzavarhatják más alkalmazások viselkedését."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"Képernyő-kompatibilitás beállítása"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Lehetővé teszi, hogy az alkalmazás szabályozza az egyéb alkalmazások képernyő-kompatibilitási módját. A kártékony alkalmazások megzavarhatják a többi alkalmazás viselkedését."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"alkalmazások hibakeresésének bekapcsolása"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Lehetővé teszi az alkalmazás számára, hogy hibakeresést végezzen egy másik alkalmazáson. A rosszindulatú alkalmazások ezzel leállíthatnak más alkalmazásokat."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"a felhasználói felület beállításainak módosítása"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Lehetővé teszi az alkalmazás számára, hogy ellenőrizze, egy csomag telepíthető-e."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"egy csomaghitelesítőhöz kötődnek"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Lehetővé teszi, hogy a tulajdonos kérelmeket nyújtson be a csomag hitelesítőivel kapcsolatban. A normál alkalmazásoknak erre soha nincs szüksége."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"soros portok elérése"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Lehetővé teszi a tulajdonos számára a soros portok elérését a SerialManager API segítségével."</string>
<string name="save_password_message" msgid="767344687139195790">"Szeretné, hogy a böngésző megjegyezze a jelszót?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Most nem"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Megjegyzés"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 49b368f..6ed5c0e 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Mengizinkan apl memindah tugas ke latar depan dan latar belakang. Apl berbahaya dapat memaksa berpindah ke depan tanpa kontrol Anda."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"menghentikan apl yang berjalan"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Memungkinkan apl menghapus tugas dan menutup aplikasinya. Apl berbahaya dapat mengganggu perilaku apl lain."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"menyetel kompatibilitas layar"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Memungkinkan apl mengontrol mode kompatibilitas layar aplikasi lain. Aplikasi berbahaya dapat merusak perilaku aplikasi lain."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"mengaktifkan debugging apl"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Mengizinkan apl mengaktifkan debugging untuk apl lain. Apl berbahaya dapat menggunakan cara ini untuk menutup apl lain."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"ubah setelan UI Anda"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Mengizinkan apl memverifikasi bahwa suatu paket dapat dipasang."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"mengikat ke pemverifikasi paket"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Mengizinkan pemegang mengajukan permintaan pemverifikasian paket. Tidak pernah dibutuhkan oleh apl normal."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"akses port serial"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Memungkinkan pemegangnya mengakses port serial menggunakan API SerialManager."</string>
<string name="save_password_message" msgid="767344687139195790">"Apakah Anda ingin peramban menyimpan sandi ini?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Tidak sekarang"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Ingat"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 46e90d3..8af1f5e 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Consente all\'applicazione di spostare attività in primo piano e in background. Le applicazioni dannose potrebbero forzare la loro impostazione in primo piano senza il tuo controllo."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"interruzione applicazioni in esecuzione"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Consente all\'applicazione di rimuovere le attività e terminare le loro applicazioni. Le applicazioni dannose potrebbero interferire con il comportamento di altre applicazioni."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"impostazione compatibilità schermo"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Consente all\'applicazione di controllare la modalità di compatibilità dello schermo di altre applicazioni. Le applicazioni dannose potrebbero disturbare il comportamento di altre applicazioni."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"attivazione debug delle applicazioni"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Consente all\'applicazione di attivare il debug per un\'altra applicazione. Le applicazioni dannose potrebbero farne uso per terminare altre applicazioni."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"modifica impostazioni UI"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Consente all\'applicazione di verificare se un pacchetto è installabile."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"associazione a verifica pacchetto"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Consente al proprietario di effettuare richieste relative alle verifiche dei pacchetti. Non dovrebbe mai essere necessario per le normali applicazioni."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"accesso alle porte seriali"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Permette al proprietario di accedere alle porte seriali utilizzando l\'API SerialManager."</string>
<string name="save_password_message" msgid="767344687139195790">"Memorizzare la password nel browser?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Non ora"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Memorizza"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 9cde4b3..5d5b9da 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"מאפשר ליישום להעביר משימות לחזית ולרקע. יישומים זדוניים עלולים לאלץ את עצמם לעבור לחזית ללא שליטה מצדך."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"עצירת יישומים פעילים"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"הרשאה זו מאפשרת ליישום להסיר משימות ולסגור את היישומים שבהם הן פועלות. יישומים זדוניים עלולים לשבש את פעולתם של יישומים אחרים."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"הגדרת תאימות מסך"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"מאפשר ליישום לשלוט במצב תאימות המסך של יישומים אחרים. יישומים זדוניים עלולים לפגוע בהתנהגות של יישומים אחרים."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"הפעלה של ניקוי באגים ביישומים"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"הרשאה זו מאפשרת ליישום להפעיל ניקוי באגים עבור יישום אחר. יישומים זדוניים עלולים להשתמש באפשרות זו כדי לסגור יישומים אחרים."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"שנה את הגדרות ממשק המשתמש שלך"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"מאפשר ליישום לאמת שחבילה ניתנת להתקנה."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"הכפפה למאמת חבילה"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"מאפשר למשתמש להגיש בקשות של מאמתי חבילות. הרשאה זו לעולם אינה נחוצה ליישומים רגילים."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"גישה ליציאות טוריות"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"מאפשר לבעלים לגשת ליציאות טוריות באמצעות ממשק ה- API של SerialManager."</string>
<string name="save_password_message" msgid="767344687139195790">"האם ברצונך שהדפדפן יזכור סיסמה זו?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"לא כעת"</string>
<string name="save_password_remember" msgid="6491879678996749466">"זכור"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 827644e..cadf935 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"タスクをフォアグラウンドやバックグラウンドに移動することをアプリに許可します。この許可を悪意のあるアプリに利用されると、悪意のあるアプリが強制的に優先される恐れがあります。"</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"実行中のアプリの停止"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"タスクの削除とアプリの終了をアプリに許可します。この許可を悪意のあるアプリケーションに利用されると、他のアプリの動作が妨害される恐れがあります。"</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"画面互換性の設定"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"他のアプリケーションの画面互換性モードをコントロールすることをアプリに許可します。この許可を悪意のあるアプリケーションに利用されると、他のアプリケーションの動作が中断される恐れがあります。"</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"アプリのデバッグの有効化"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"別のアプリをデバッグモードにすることをアプリに許可します。この許可を悪意のあるアプリに利用されると、他のアプリが強制終了される恐れがあります。"</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"UI設定の変更"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"パッケージがインストール可能かどうか確認することをアプリに許可します。"</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"パッケージベリファイアにバインド"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"パッケージベリファイアのリクエストを所有者に許可します。通常のアプリでは不要です。"</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"シリアルポートへのアクセス"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"SerialManager APIを使用してシリアルポートにアクセスすることを所有者に許可します。"</string>
<string name="save_password_message" msgid="767344687139195790">"このパスワードをブラウザで保存しますか?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"今は保存しない"</string>
<string name="save_password_remember" msgid="6491879678996749466">"保存"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 14735b0..031e9f5 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"앱이 작업을 포그라운드나 백그라운드로 이동할 수 있도록 허용합니다. 이 경우 악성 앱이 사용자의 조작 없이 앞으로 이동할 수 있습니다."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"실행 중인 앱 중지"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"애플리케이션이 작업을 삭제하거나 다른 애플리케이션을 중지시킬 수 있도록 허용합니다. 이 경우 악성 애플리케이션이 다른 애플리케이션의 동작을 멈추게 할 수 있습니다."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"화면 호환성 설정"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"앱이 다른 애플리케이션의 화면 호환성 모드를 제어할 수 있도록 허용합니다. 이 경우 악성 애플리케이션이 다른 애플리케이션의 동작을 멈추게 할 수 있습니다."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"앱 디버깅 사용"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"애플리케이션이 다른 애플리케이션에 대해 디버깅을 사용할 수 있도록 허용합니다. 이 경우 악성 애플리케이션이 다른 애플리케이션을 중지시킬 수 있습니다."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"UI 설정 변경"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"앱이 패키지가 설치 가능한지 확인할 수 있도록 허용합니다."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"패키지 인증 연결"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"권한을 가진 프로그램이 패키지 인증을 요청할 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"직렬 포트에 액세스"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"SerialManager API를 사용하여 권한을 가진 프로그램이 직렬 포트에 액세스할 수 있도록 합니다."</string>
<string name="save_password_message" msgid="767344687139195790">"브라우저에 이 비밀번호를 저장하시겠습니까?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"나중에"</string>
<string name="save_password_remember" msgid="6491879678996749466">"저장"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index a83b064..22830ac 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Leidžiama programai užduotis perkelti į priekinį planą ir į foną. Kenkėjiškos programos gali priverstinai persikelti į priekį be jūsų įsikišimo."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"sustabdyti vykdomas programas"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Leidžiama programai pašalinti užduotis ir panaikinti jų programas. Kenkėjiškos programos gali trikdyti kitų programų veikimą."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"nustatyti ekrano suderinamumo režimą"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Programai leidžiama valdyti kitų programų ekrano suderinamumo režimą. Kenkėjiškos programos gali kliudyti veikti kitoms programoms."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"įgalinti programos derinimą"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Leidžiama programai įjungti kitos programos derinimą. Kenkėjiškos programos gali tai naudoti, kad išjungtų kitas programas."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"keisti UI nustatymus"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Leidžiama programai patikrinti, ar paketą galima įdiegti."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"susaistyti su paketo tikrinimo programa"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Savininkui leidžiama teikti užklausas patikrinti paketą. Įprastoms programoms to neturėtų prireikti."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"pasiekti nuosekliuosius prievadus"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Leidžiama savininkui pasiekti nuosekliuosius prievadus naudojant „SerialManager“ API."</string>
<string name="save_password_message" msgid="767344687139195790">"Ar norite, kad naršyklė atsimintų šį slaptažodį?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Ne dabar"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Atsiminti"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 170653a..f716cb9 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Ļauj lietotnei pārvietot uzdevumus priekšplānā un fonā. Ļaunprātīgas lietotnes var tikt izvirzītas priekšplānā bez jūsu vadības."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"apturēt izmantoto lietotņu darbību"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Ļauj lietotnei noņemt uzdevumus un pārtraukt to lietotņu darbību. Ļaunprātīgas lietotnes var traucēt citu lietotņu darbību."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"Ekrāna saderības noteikšana"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Ļauj lietotnei kontrolēt citu lietotņu ekrāna saderības režīmu. Ļaunprātīgas lietojumprogrammas var mainīt citu lietojumprogrammu darbību."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"iespējot lietotnes atkļūdošanu"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Ļauj lietotnei ieslēgt citas lietotnes atkļūdošanu. Ļaunprātīgas lietotnes to var izmantot, lai pārtrauktu citu lietotņu darbību."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"mainīt lietotāja saskarnes iestatījumus"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Ļauj lietotnei verificēt, vai pakotne ir instalējama."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"saistīšana ar pakotnes verificētāju"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Ļauj īpašniekam sūtīt pakotņu verificētāju pieprasījumus. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"piekļuve seriālajiem portiem"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Ļauj īpašniekam piekļūt seriālajiem portiem, izmantojot SerialManager API."</string>
<string name="save_password_message" msgid="767344687139195790">"Vai vēlaties, lai pārlūkprogrammā tiktu saglabāta šī parole?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Ne tagad"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Atcerēties"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 498bd83..6aa9e4c 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Membenarkan apl untuk memindahkan tugasan ke latar depan dan latar belakang. Apl hasad boleh memaksa diri mereka ke hadapan tanpa kawalan anda."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"hentikan apl yang sedang dijalankan"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Membenarkan apl untuk mengalih keluar tugasan dan melupuskan aplnya. Apl hasad boleh mengganggu tingkah laku apl lain."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"tetapkan keserasian skrin"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Membenarkan apl mengawal mod keserasian skrin aplikasi lain. Aplikasi hasad mungkin mematahkan kelakuan aplikasi lain."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"dayakan penyahpepijatan apl"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Membenarkan apl untuk menghidupkan penyahpepijatan untuk apl lain. Apl hasad boleh menggunakannya untuk menghapuskan apl lain."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"tukar tetapan UI anda"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Membenarkan apl untuk mengesahkan bahawa pakej boleh dipasang."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"ikat kepada pengesah pakej"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Membenarkan pemegang membuat permintaan pengesah pakej. Tidak sekali-kali diperlukan untuk apl normal."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"akses port bersiri"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Membenarkan pemegang mengakses port bersiri menggunakan API SerialManager."</string>
<string name="save_password_message" msgid="767344687139195790">"Adakah anda mahu penyemak imbas mengingati kata laluan ini?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Bukan sekarang"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Ingat"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 084b281..b1b3cbe 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Lar appen flytte oppgaver til forgrunnen eller bakgrunnen. Ondsinnede apper kan tvinge seg frem til forgrunnen utenfor din kontroll."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"avslutte apper som kjører"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Lar appen fjerne oppgaver og avslutte apper. Ondsinnede apper kan forstyrre atferden til andre apper."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"angi skjermkompatibilitet"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Lar appen kontrollere modus for skjermkompatibilitet i andre apper. Skadelige apper kan ødelegge funksjoner i andre apper."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"aktivere feilsøking av app"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Lar appen slå av feilsøking for andre apper. Ondsinnede apper kan bruke dette til å avslutte andre apper."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"endre innstillingene for brukergrensesnitt"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Lar appen bekrefte om en pakke kan installeres."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"bind til en pakkeverifikator"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Lar innehaveren sende forespørsler om pakkeverifikatorer. Skal aldri være nødvendig for normale apper."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"tilgang til serielle porter"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Gir innehaveren tilgang til serielle porter ved hjelp av SerialManager API."</string>
<string name="save_password_message" msgid="767344687139195790">"Ønsker du at nettleseren skal huske dette passordet?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Ikke nå"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Husk"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index bc23697..9409445 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Hiermee kan de app taken naar de voor- en achtergrond verplaatsen. Schadelijke apps kunnen zichzelf op de voorgrond plaatsen zonder dat u hier iets aan kunt doen."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"actieve apps stoppen"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Hiermee kan de app taken verwijderen en apps sluiten. Schadelijke apps kunnen het gedrag van andere apps verstoren."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"schermcompatibiliteit instellen"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Toestaan dat de app de schermcompatibiliteitsmodus van andere apps beheert. Schadelijke apps kunnen het gedrag van andere apps verstoren."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"foutopsporing in apps inschakelen"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Hiermee kan de app de foutopsporing voor een andere app inschakelen. Schadelijke apps kunnen dit gebruiken om andere apps af te sluiten."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"uw UI-instellingen wijzigen"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Hiermee kan de app controleren of een pakket kan worden geïnstalleerd."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"koppelen aan pakketcontroleprogramma"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Hiermee kan de houder verzoeken indienen voor pakketcontroles. Nooit vereist voor normale apps."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"toegang krijgen tot seriële poorten"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"De houder toestaan toegang tot seriële poorten te krijgen met de SerialManager API."</string>
<string name="save_password_message" msgid="767344687139195790">"Wilt u dat de browser dit wachtwoord onthoudt?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Niet nu"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Onthouden"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 565fa79..8564dc7 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Pozwala aplikacji na przenoszenie zadań między tłem i pierwszym planem. Złośliwe aplikacje mogą wymusić przeniesienie się na pierwszy plan bez Twojego udziału."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"zatrzymywanie uruchomionych aplikacji"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Umożliwia aplikacji usuwanie zadań i kończenie powiązanych z nimi aplikacji. Złośliwe aplikacje mogą zakłócić działanie innych aplikacji."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"ustaw zgodność ekranu"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Pozwala aplikacji na sterowanie trybem zgodności ekranu innych aplikacji. Złośliwe aplikacje mogą zmienić zachowanie innych aplikacji."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"włączenie debugowania aplikacji"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Pozwala aplikacji na włączenie debugowania innej aplikacji. Złośliwe aplikacje mogą to wykorzystać do kończenia pracy innych programów."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"zmienianie ustawień interfejsu użytkownika"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Pozwala aplikacji na zweryfikowanie, czy pakiet można zainstalować."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"powiązanie z weryfikatorem pakietów"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Pozwala na wysyłanie żądań weryfikacji pakietu. To uprawnienie nie powinno być potrzebne zwykłym aplikacjom."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"dostęp do portów szeregowych"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Umożliwia posiadaczowi dostęp do portów szeregowych przy użyciu interfejsu API narzędzia SerialManager."</string>
<string name="save_password_message" msgid="767344687139195790">"Czy chcesz, aby zapamiętać to hasło w przeglądarce?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Nie teraz"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Zapamiętaj"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 28b8463..a162aa0 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Permite à aplicação mover tarefas para primeiro e segundo plano. As aplicações maliciosas podem impor-se em primeiro plano sem o controlo do utilizador."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"parar aplicações em execução"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Permite que a aplicação remova tarefas e elimine as respetivas aplicações. As aplicações maliciosas podem perturbar o comportamento de outras aplicações."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"definir compatibilidade de ecrã"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Permite que a aplicação controle o modo de compatibilidade de ecrã de outras aplicações. As aplicações maliciosas poderão afetar o comportamento de outras aplicações."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"ativar depuração da aplicação"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Permite que a aplicação ative a depuração para outra aplicação. As aplicações maliciosas podem utilizar isto para eliminar outras aplicações."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"alterar definições da IU"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Permite que a aplicação verifique se um pacote é instalável."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"vincular a um verificador de pacotes"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Permite ao titular solicitar verificadores de pacotes. Nunca deverá ser necessário para aplicações normais."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"aceder a portas série"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Permite ao titular aceder a portas de série através da API SerialManager."</string>
<string name="save_password_message" msgid="767344687139195790">"Quer que o browser memorize esta palavra-passe?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Agora não"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Lembrar"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index cf6627e..5c16708 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Permite que o aplicativo mova tarefas para o primeiro plano e para o plano de fundo. Aplicativos maliciosos podem forçar-se para a primeiro plano sem que você tenha controle sobre a ação."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"parar os aplicativos em execução"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Permite que um aplicativo remova tarefas e elimine seus aplicativos. Aplicativos maliciosos podem interferir no comportamento de outros aplicativos."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"definir a compatibilidade de tela"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Permite que o aplicativo controle o modo de compatibilidade de tela de outros aplicativos. Aplicativos maliciosos podem interromper o comportamento de outros aplicativos."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"ativar depuração do aplicativo"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Permite que o aplicativo ative a depuração para outro aplicativo. Aplicativos maliciosos podem usar esse recurso para cancelar outros aplicativos."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"alterar as suas configurações de UI"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Permite que o aplicativo verifique se um pacote pode ser instalado."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"vincular a um verificador de pacote"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Permite que o titular solicite verificadores de pacote. Nunca deve ser necessário para aplicativos normais."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"acessar portas seriais"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Permite que o detentor tenha acesso a portas seriais usando a API SerialManager."</string>
<string name="save_password_message" msgid="767344687139195790">"Deseja que o navegador lembre desta senha?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Agora não"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Lembrar"</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index a900840..57daee7 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -1151,6 +1151,10 @@
<skip />
<!-- no translation found for permdesc_bindPackageVerifier (3180741773233862126) -->
<skip />
+ <!-- no translation found for permlab_serialPort (546083327654631076) -->
+ <skip />
+ <!-- no translation found for permdesc_serialPort (2991639985224598193) -->
+ <skip />
<string name="save_password_message" msgid="767344687139195790">"Vulais Vus ch\'il navigatur memorisescha quest pled-clav?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Betg ussa"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Memorisar"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 44919ac..fe3687f 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Permite aplicaţiei să mute activităţile în prim-plan şi în fundal. Aplicaţiile rău intenţionate pot să apară forţat în prim-plan, fără ca dvs. să puteţi controla acest lucru."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"oprire aplicaţii care rulează"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Permite aplicaţiei să elimine sarcini şi să închidă aplicaţiile corespunzătoare acestora. Aplicaţiile rău intenţionate pot perturba comportamentul altor aplicaţii."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"setaţi compatibilitatea ecranului"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Permite aplicaţiei să controleze modul de compatibilitate a ecranului pentru alte aplicaţii. Aplicaţiile rău intenţionate pot afecta comportamentul altor aplicaţii."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"activare depanare aplicaţie"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Permite aplicaţiei să activeze depanarea pentru o altă aplicaţie. Aplicaţiile rău intenţionate pot să utilizeze această permisiune pentru a închide alte aplicaţii."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"modificare setări UI"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Permite aplicaţiei să verifice dacă un pachet poate fi instalat."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"conectare la un verificator de pachete"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Permite proprietarului să efectueze solicitări pentru verificatori de pachete. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"acces la porturi seriale"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Permite posesorului accesul la porturile serial utilizând API-ul SerialManager."</string>
<string name="save_password_message" msgid="767344687139195790">"Doriţi ca browserul să reţină această parolă?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Nu acum"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Reţineţi"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index ace79d3..55468a0 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Приложение сможет перемещать задачи в режим активного или фонового выполнения. Вредоносные программы смогут переводить себя в активный режим без вашего ведома."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"остановка запущенных приложений"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Приложение сможет удалять задачи и собственные программы. Вредоносное ПО при этом сможет нарушать работу других приложений."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"Установка режима совместимости"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Приложение сможет управлять режимом совместимости экрана других приложений. Вредоносное ПО может привести к сбоям в работе других программ."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"включение отладки приложений"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Приложение сможет включать отладку для другой программы. Вредоносное ПО сможет таким образом останавливать работу других приложений."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"изменять настройки пользовательского интерфейса"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Приложение сможет проверять возможность установки пакетов."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"связываться с верификатором пакетов"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Приложение сможет запрашивать проверку пакетов. Это разрешение не используется обычными приложениями."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"доступ к последовательным портам"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Открыть владельцу доступ к последовательным портам с помощью SerialManager API."</string>
<string name="save_password_message" msgid="767344687139195790">"Вы хотите, чтобы браузер запомнил этот пароль?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Не сейчас"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Запомнить"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 8cb518c..7d1aa78 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Umožňuje aplikácii presúvať úlohy do popredia a pozadia. Škodlivé aplikácie sa môžu pretlačiť do popredia bez vášho vedomia."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"zastaviť spustené aplikácie"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Umožňuje aplikácii odstrániť úlohy a ukončiť ich aplikácie. Škodlivé aplikácie môžu narušiť správanie iných aplikácií."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"nastaviť kompatibilitu obrazovky"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Umožňuje aplikácii ovládať režim kompatibility obrazovky v ostatných aplikáciách. Škodlivé aplikácie môžu narušiť správanie ostatných aplikácií."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"povoliť ladenie aplikácií"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Umožňuje aplikácii zapnúť ladenie inej aplikácie. Škodlivé aplikácie môžu pomocou tohto nastavenia ukončiť iné aplikácie."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"zmeny vašich nastavení používateľského rozhrania"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Umožňuje aplikácii overiť, či je možné balík nainštalovať."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"naviazať na overovateľa balíka"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Umožňuje držiteľovi podávať žiadosti o overenie balíkov. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"prístup k sériovým portom"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Držiteľa oprávňuje na prístup k sériovým portom pomocou rozhrania API SerialManager."</string>
<string name="save_password_message" msgid="767344687139195790">"Chcete, aby si prehliadač zapamätal toto heslo?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Teraz nie"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Zapamätať"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index e7a6c07..dfedb9a 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Programu omogoča premikanje opravil v ospredje in ozadje. Zlonamerni programi se lahko brez vašega nadzora vsilijo v ospredje."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"ustavitev programov, ki se izvajajo"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Programu omogoča odstranjevanje opravil in zapiranje njihovih programov. Zlonamerni programi lahko motijo delovanje drugih programov."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"nastavitev združljivosti zaslona"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Programu omogoča nadzor združljivostnega načina zaslona drugih programov. Zlonamerni programi lahko prekinejo delovanje drugih programov."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"omogočanje iskanja in odpravljanja napak v programu"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Programu omogoča vklop funkcije za odpravljanje napak za drug program. Zlonamerni programi lahko to uporabijo za zapiranje drugih programov."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"spreminjanje nastavitev UV"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Programu omogoča, da preveri, ali je paket mogoče namestiti."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"poveži s preverjanjem paketov"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Imetniku omogoča zahtevanje preverjanja paketov. Tega nikoli ni treba uporabiti za navadne programe."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"dostop do serijskih vrat"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Imetniku omogoča, da z API-jem za SerialManager dostopa do serijskih vrat."</string>
<string name="save_password_message" msgid="767344687139195790">"Ali želite, da si brskalnik zapomni to geslo?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Ne zdaj"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Zapomni si"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 2374f59..2a2104f 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Дозвољава апликацији да премешта задатке у први план и у позадину. Злонамерне апликације могу на тај начин да принудно пређу у први план без ваше контроле."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"заустављање покренутих апликација"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Дозвољава апликацији да уклања задатке и уништава њихове апликације. Злонамерне апликације могу да поремете понашање других апликација."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"подешавање компатибилности екрана"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Дозвољава апликацији да контролише режим компатибилности екрана других апликација. Злонамерне апликације могу да угрозе понашање других апликација."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"омогућавање отклањања грешака у апликацији"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Дозвољава апликацији да укључи уклањање грешака за другу апликацију. Злонамерне апликације могу то да искористе за онемогућавање других апликација."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"промена подешавања корисничког интерфејса"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Дозвољава апликацији да верификује да ли је пакет могуће инсталирати."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"обавезивање на верификатор пакета"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Омогућава да власник упућује захтеве верификаторима пакета. Уобичајене апликације никада не би требало да је користе."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"приступ серијским портовима"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Омогућава власнику да приступи серијским портовима помоћу SerialManager API-ја."</string>
<string name="save_password_message" msgid="767344687139195790">"Желите ли да прегледач запамти ову лозинку?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Не сада"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Запамти"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 26e1ea5..0067a12 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Tillåter att appen flyttar uppgifter till förgrunden eller bakgrunden. Skadliga appar kan tvinga sig till förgrunden utan att du kan styra det."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"avsluta appar som körs"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Tillåter att appen tar bort uppgifter och avslutar appar. Skadliga appar kan störa funktionen i andra appar."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"ange skärmkompatibilitet"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Tillåter att appen styr skärmkompatibilitetsläget i andra appar. Skadliga appar kan störa andra appars funktion."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"aktivera felsökning av appar"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Tillåter att appen aktiverar felsökning för en annan app. Skadliga appar kan använda detta för att avsluta andra appar."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"ändra dina gränssnittsinställningar"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Tillåter att appen kontrollerar om ett paket går att installera."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"binda till en paketverifierare"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Tillåter att innehavaren skickar förfrågningar till paketverifierare. Det ska inte behövas för vanliga appar."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"åtkomst till serieportar"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Innebär att innehavaren får åtkomst till serieportar med programmeringsgränssnittet för SerialManager."</string>
<string name="save_password_message" msgid="767344687139195790">"Vill du att webbläsaren ska komma ihåg lösenordet?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Inte nu"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Kom ihåg"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 22ce660..369853c 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Inaruhusu programu kusongesha kazi kwenye mandhari-mbele na mandhari-nyuma. Programu hasidi zinaweza kujilazimisha mbele bila udhibiti wako."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"Komesha programu zinazoendeshwa"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Huruhusu programu kuondoa majukumu na kuua programu zao. Programu hasidi zinaweza kutatiza tabia ya programu zingine."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"weka utangamano wa skrini"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Huruhusu programu kudhibiti hali ya utangamano wa skrini ya programu zingine. Programu hasidi zinaweza kuvunja mwenendo wa programu zingine."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"wezesha utatuaji wa programu"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Huruhusu programu kuwasha kueua cha programu nyingine. Programu hasidi huenda zikatumia hii ili kuua programu nyingine."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"badilisha mipangilio yako ya onyesho"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Inaruhusu programu kuthibitisha kuwa furushi linaweza kusakinishwa."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"Funga kwa kithibitishaji cha furushi"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Inaruhusu mmiliki kutuma maombi ya vibainishi furushi. Kamwe hazitahitajika kwa programu za kawaida."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"kituo tambulishi cha ufikivu"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Inaruhusu mmiliki kufikia vituo tambulishi kwa kutumia KisimamiziTambulishi cha API."</string>
<string name="save_password_message" msgid="767344687139195790">"Unataka kuvinjari ili ukumbuke nenosiri hili?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Si Sasa"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Kumbuka"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 0ff883d..debe568 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"อนุญาตให้แอปพลิเคชันย้ายงานไปยังส่วนหน้าและพื้นหลัง แอปพลิเคชันที่เป็นอันตรายอาจบังคับตัวเองให้ไปที่ส่วนหน้าโดยไม่มีการควบคุมจากคุณ"</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"หยุดแอปพลิเคชันที่ทำงานอยู่"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"อนุญาตให้แอปพลิเคชันลบงานออกและยุติแอปพลิเคชันต่างๆ ของงานนั้น แอปพลิเคชันที่เป็นอันตรายอาจทำให้แอปพลิเคชันอื่นๆ ทำงานได้ไม่ถูกต้อง"</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"ตั้งค่าความเข้ากันได้ของหน้าจอ"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"อนุญาตให้แอปพลิเคชันควบคุมโหมดความเข้ากันได้ของหน้าจอของแอปพลิเคชันอื่น แอปพลิเคชันที่เป็นอันตรายอาจทำให้แอปพลิเคชันอื่นทำงานผิดพลาด"</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"เปิดใช้งานการแก้ไขบกพร่องของแอปพลิเคชัน"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"อนุญาตให้แอปพลิเคชันเปิดการแก้ไขข้อบกพร่องสำหรับแอปพลิเคชันอื่น แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ยุติการทำงานของแอปพลิเคชันอื่นๆ ได้"</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"เปลี่ยนการตั้งค่า UI ของคุณ"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"อนุญาตให้แอปพลิเคชันยืนยันว่าแพคเกจสามารถติดตั้งได้หรือไม่"</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"เชื่อมโยงกับการยืนยันแพคเกจ"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"อนุญาตให้ผู้ใช้ส่งคำขอให้มีการยืนยันแพคเกจ ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"เข้าถึงพอร์ตอนุกรม"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"อนุญาตให้ผู้ถือสามารถเข้าถึงพอร์ตอนุกรมโดยใช้ SerialManager API"</string>
<string name="save_password_message" msgid="767344687139195790">"คุณต้องการให้เบราว์เซอร์จำรหัสผ่านนี้หรือไม่"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"ยังไม่ใช้งานขณะนี้"</string>
<string name="save_password_remember" msgid="6491879678996749466">"จำไว้"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 889b3a9..e74e309 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Pinapayagan ang app na ilipat ang mga gawain sa foreground at background. Maaaring puwersahin ng nakakahamak na apps ang mga sarili nito sa harapan nang wala ang iyong pagkontrol."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"ihinto ang pagpapatakbo ng apps"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Pinapayagan ang app na mag-alis ng mga gawain at i-off ang apps nito. Maaaring maantala ng nakakahamak na apps ang pagkilos ng iba pang apps."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"itakda ang pagkakatugma ng screen"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Pinapayagan ang app na kontrolin ang mode ng pagkakatugma ng screen ng iba pang mga application. Maaaring sirain ng mga nakakahamak na application ang pag-uugali ng iba pang mga application."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"paganahin ang pag-debug ng app"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Pinapayagan ang app na i-on ang pag-debug para sa isa pang app. Maaari itong gamitin ng nakakahamak na apps upang i-off ang iba pang apps."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"baguhin ang iyong mga setting ng UI"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Pinapayagan ang app na i-verify kung ang isang package ay nai-install."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"sumailalim sa taga-verify ng package"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Pinapayagan ang may-ari na gumawa ng mga kahilingan ng mga taga-verify ng package. Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"mag-access sa mga serial port"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Binibigyang-daan ang may-ari na mag-access ng mga serial port gamit ang SerialManager API."</string>
<string name="save_password_message" msgid="767344687139195790">"Gusto mo bang tandaan ng browser ang password na ito?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Hindi ngayon"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Tandaan"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 07e4ec9..8d52c8c 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Uygulamaya, görevleri ön plana ve arka plana taşıma izni verir. Kötü amaçlı uygulamalar kendilerini sizin denetiminiz dışında ön plana taşıyabilir."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"çalışan uygulamaları durdur"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Uygulamaya, görevleri kaldırma ve bunlara ait uygulamaları kapatma izni verir. Kötü amaçlı uygulamalar diğer uygulamaların çalışmasını bozabilir."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"ekran uyumluluğunu ayarla"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Uygulamaya diğer uygulamaların ekran uyumluluk modunu denetleme izni verir. Kötü amaçlı uygulamalar diğer uygulamaların çalışma şeklini bozabilir."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"uygulama hata ayıklamayı etkinleştir"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Uygulamaya, başka bir uygulama için hata ayıklamayı açma izni verir. Kötü amaçlı uygulamalar diğer uygulamaları kaldırmak için bunu kullanabilir."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"kullanıcı arayüzü ayarlarınızı değiştirin"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Uygulamaya, bir paketin yüklenebilir olduğunu doğrulama izni verir."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"paket doğrulayıcıya bağlan"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Cihazın sahibine, paket doğrulayıcıları için istek yapma izni verir. Normal uygulamalar için gerekli olmaz."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"seri bağlantı noktalarına eriş"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"İzin sahibinin, SerialManager API\'sını kullanarak seri bağlantı noktalarına erişmesine olanak sağlar."</string>
<string name="save_password_message" msgid="767344687139195790">"Tarayıcının bu şifreyi anımsamasını istiyor musunuz?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Şimdi değil"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Anımsa"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index ac2ea3c..9d049cf 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Дозволяє програмі переміщувати завдання в активні чи фонові вікна. Шкідливі програми можуть примусово ставати активними без вашого відома."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"зупиняти запущені програми"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Дозволяє програмі видаляти завдання та примусово припиняти роботу відповідних програм. Шкідливі програми можуть переривати роботу інших програм."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"установити сумісність екрана"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Дозволяє програмі контролювати режим сумісності екрана інших програм. Шкідливі програми можуть переривати роботу інших програм."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"вмикати налагодження програми"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Дозволяє програмі вмикати налагодження для іншої програми. Шкідливі програми можуть використовувати це для примусового припинення роботи інших програм."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"змін. налашт. інтерф. кор."</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Дозволяє програмі перевіряти можливість встановлення пакета."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"прив’язуватися до програми перевірки пакетів"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Дозволяє власникові робити запити на програми перевірки пакетів. Ніколи не застосовується для звичайних програм."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"отримувати доступ до послідовних портів"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Дозволяє власнику отримувати доступ до послідовних портів за допомогою API SerialManager."</string>
<string name="save_password_message" msgid="767344687139195790">"Хочете, щоб переглядач запам\'ятав цей пароль?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Не зараз"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Запам\'ятати"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 9f2fe0c..8166606 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Cho phép ứng dụng di chuyển công việc sang nền trước và nền sau. Ứng dụng độc hại có thể tự hiển thị ở nền trước mà không chịu sự kiểm soát của bạn."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"dừng các ứng dụng đang chạy"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Cho phép ứng dụng xóa công việc và loại bỏ các ứng dụng của chúng. Ứng dụng độc hại có thể làm gián đoạn hoạt động của các ứng dụng khác."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"đặt độ tương thích màn hình"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Cho phép ứng dụng kiểm soát chế độ tương thích màn hình của ứng dụng khác. Các ứng dụng độc hại có thể phá vỡ hoạt động của các ứng dụng khác."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"bật gỡ lỗi ứng dụng"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Cho phép ứng dụng bật gỡ lỗi cho một ứng dụng khác. Ứng dụng độc hại có thể sử dụng quyền này để loại bỏ những ứng dụng khác."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"thay đổi cài đặt giao diện người dùng của bạn"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Cho phép ứng dụng xác minh gói có thể cài đặt."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"liên kết với trình xác minh gói"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Cho phép chủ sở hữu yêu cầu trình xác minh gói. Không cần thiết cho các ứng dụng thông thường."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"truy cập cổng nối tiếp"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Cho phép chủ sở hữu truy cập cổng nối tiếp sử dụng API SerialManager."</string>
<string name="save_password_message" msgid="767344687139195790">"Bạn có muốn trình duyệt nhớ mật khẩu này không?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Không phải bây giờ"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Nhớ"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 89f5ad0..a9f431c 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"允许应用程序将任务移动到前台和后台。恶意应用程序可能会不受您的控制,强行让自己处于前台。"</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"停止正在运行的应用程序"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"允许该应用程序删除任务并终止这些任务的应用程序。恶意应用程序可以籍此影响其他应用程序的行为。"</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"设置屏幕兼容性"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"允许应用程序控制其他应用程序的屏幕兼容模式。恶意应用程序可以籍此影响其他应用程序的行为。"</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"启用应用程序调试"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"允许该应用程序对其他应用程序启用调试。恶意应用程序可以籍此终止其他的应用程序。"</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"更改用户界面设置"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"允许应用程序验证程序包是否可以安装。"</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"绑定到软件包验证程序"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"允许用户请求使用程序包验证程序。普通应用程序绝不需要此权限。"</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"访问串行端口"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"允许持有人使用 SerialManager API 访问串行端口。"</string>
<string name="save_password_message" msgid="767344687139195790">"是否希望浏览器记住此密码?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"暂不保存"</string>
<string name="save_password_remember" msgid="6491879678996749466">"记住"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index ededae8..5aee830 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"允許應用程式將工作移至前景或背景。請注意,惡意應用程式可能利用此功能自行移動至前景。"</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"停止執行中的應用程式"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"允許應用程式移除工作並終止執行工作的應用程式。請注意,惡意應用程式可能利用此功能干擾其他應用程式的行為。"</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"設定螢幕相容性"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"允許應用程式控制其他應用程式的螢幕相容性模式。惡意應用程式可能藉此破壞其他應用程式的正常運作。"</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"啟用應用程式偵錯"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"允許應用程式為其他程式開啟偵錯功能。提醒您,惡意應用程式可能會利用這個功能終止其他應用程式。"</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"變更介面設定"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"允許應用程式驗證是否可安裝特定套件。"</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"繫結至套件驗證程序"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"允許應用程式要求驗證套件 (一般應用程式不需使用)。"</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"存取序列埠"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"允許應用程式使用 SerialManager API 存取序列埠。"</string>
<string name="save_password_message" msgid="767344687139195790">"是否記住此密碼?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"現在不要"</string>
<string name="save_password_remember" msgid="6491879678996749466">"記住"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 3ee95be..36da63d 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -215,10 +215,8 @@
<string name="permdesc_reorderTasks" msgid="4175137612205663399">"Ivumela insiza ukuthi ihambise izenzo ziye ngaphambili kanye nasemumva. Izinsiza ezinobungozi zingaziphoqelela ukuth iziye phambili ngaphandle kokulawula kwakho."</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"misa izinsiza ezisebenzayo"</string>
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Vumela ukuthi insiza isuse okumele kwenziwe ibulale nezinsiza zakho. Izinsiza eziwubungozi zingaphazamisa ukusebenza kwezinye izinsiza."</string>
- <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
- <skip />
- <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
- <skip />
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"misa ukuhambelana kwesikrini"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Ivumela uhlelo lokusebenza ukulawula imodi yokuhambelana kwesikrini kwezinye izinhlelo zokusebenza. Izinhlelo zokusebenza ezinonya zingase zephule ukuziphatha kwezinye izinhlelo zokusebenza."</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"vumela insiza ilungise inkinga"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Ivumela insiza ukuthi ivule uhlelo lokulungisa lwenye insiza. Izinsiza ezinobungozi zingasebenzisa lokhu ukubulala ezinye izinsiza."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"shintsha izilungiselelo zakho ze-UI"</string>
@@ -764,6 +762,8 @@
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Ivumela ukuthi isisetshenziswa siqinisekise ukuthi ngabe iphakheji iyafakeka."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"bopha okokuqinisekisa iphakheji"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Ivumela umnikazi ukuthi enze izicelo zezinsiza eziqinisekisa iphakheji. Akumele kudingeke ekusetshenzisweni okujwayelekile."</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"finyelela kuma- serial port"</string>
+ <string name="permdesc_serialPort" msgid="2991639985224598193">"Ivumela umnikai ukuthi athole inombolo ye-serial ukue angene kwiindawo ze-serial esebenzisa i-SerialManager API."</string>
<string name="save_password_message" msgid="767344687139195790">"Ingabe ufuna ukuba isiphequluli sikhumbule lephasiwedi?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Hha yi manje"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Khumbula"</string>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e84cb5c..4e55b4f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -218,6 +218,7 @@
<java-symbol type="bool" name="config_allowActionMenuItemTextWithIcon" />
<java-symbol type="bool" name="config_bluetooth_adapter_quick_switch" />
<java-symbol type="bool" name="config_bluetooth_sco_off_call" />
+ <java-symbol type="bool" name="config_alwaysUseCdmaRssi" />
<java-symbol type="bool" name="config_duplicate_port_omadm_wappush" />
<java-symbol type="bool" name="config_enable_emergency_call_while_sim_locked" />
<java-symbol type="bool" name="config_enable_puk_unlock_screen" />
@@ -1083,6 +1084,7 @@
<java-symbol type="style" name="ActiveWallpaperSettings" />
<java-symbol type="style" name="Animation.InputMethodFancy" />
<java-symbol type="style" name="Animation.Wallpaper" />
+ <java-symbol type="style" name="Animation.RecentApplications" />
<java-symbol type="style" name="Animation.ZoomButtons" />
<java-symbol type="style" name="PreviewWallpaperSettings" />
<java-symbol type="style" name="TextAppearance.SlidingTabActive" />
@@ -3494,4 +3496,6 @@
=============================================================== -->
<public type="attr" name="isolatedProcess" id="0x010103a7" />
+ <public type="attr" name="textDirection"/>
+
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 4995d2c..c95dddd 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2708,11 +2708,6 @@
<!-- Do not translate. Default access point SSID used for tethering -->
<string name="wifi_tether_configure_ssid_default" translatable="false">AndroidAP</string>
- <!-- Wi-Fi p2p dialog title-->
- <string name="wifi_p2p_dialog_title">Wi-Fi Direct</string>
- <string name="wifi_p2p_turnon_message">Start Wi-Fi Direct. This will turn off Wi-Fi client/hotspot.</string>
- <string name="wifi_p2p_failed_message">Couldn\'t start Wi-Fi Direct.</string>
-
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="wifi_p2p_invitation_sent_title">Invitation sent</string>
@@ -2723,9 +2718,6 @@
<string name="wifi_p2p_enter_pin_message">Type the required PIN: </string>
<string name="wifi_p2p_show_pin_message">PIN: </string>
- <string name="wifi_p2p_enabled_notification_title">Wi-Fi Direct is on</string>
- <string name="wifi_p2p_enabled_notification_message">Touch for settings</string>
-
<!-- Name of the dialog that lets the user choose an accented character to insert -->
<string name="select_character">Insert character</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 571c4ad..610bad8 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -198,8 +198,10 @@
<!-- A special animation we can use for recent applications,
for devices that can support it (do alpha transformations). -->
<style name="Animation.RecentApplications">
- <item name="windowEnterAnimation">@anim/fade_in</item>
- <item name="windowExitAnimation">@anim/fade_out</item>
+ <item name="windowEnterAnimation">@anim/recents_fade_in</item>
+ <item name="windowShowAnimation">@anim/recents_fade_in</item>
+ <item name="windowExitAnimation">@anim/recents_fade_out</item>
+ <item name="windowHideAnimation">@anim/recents_fade_out</item>
</style>
<!-- A special animation value used internally for popup windows. -->
diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
index a781472..76b702e 100644
--- a/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
+++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
@@ -90,6 +90,7 @@
*/
@LargeTest
public void testWifiDownload() throws Exception {
+ mConnectionUtil.wifiTestInit();
assertTrue("Could not connect to wifi!", setDeviceWifiAndAirplaneMode(mSsid));
downloadFile();
}
@@ -143,6 +144,7 @@
*/
@LargeTest
public void testWifiUpload() throws Exception {
+ mConnectionUtil.wifiTestInit();
assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
uploadFile();
}
@@ -197,6 +199,7 @@
*/
@LargeTest
public void testWifiDownloadWithDownloadManager() throws Exception {
+ mConnectionUtil.wifiTestInit();
assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
downloadFileUsingDownloadManager();
}
@@ -286,6 +289,8 @@
* @return true if we successfully connect to mobile data.
*/
public boolean hasMobileData() {
+ assertTrue(mConnectionUtil.waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
+ State.CONNECTED, ConnectionUtil.LONG_TIMEOUT));
assertTrue("Not connected to mobile", mConnectionUtil.isConnectedToMobile());
assertFalse("Still connected to wifi.", mConnectionUtil.isConnectedToWifi());
return mConnectionUtil.hasData();
diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
index dfcbba9..7499f68 100644
--- a/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
+++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
@@ -57,7 +57,7 @@
private static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; // 10 seconds
private static final int WIFI_SCAN_TIMEOUT = 50 * 1000;
public static final int SHORT_TIMEOUT = 5 * 1000;
- public static final int LONG_TIMEOUT = 10 * 1000;
+ public static final int LONG_TIMEOUT = 120 * 1000; // 2 minutes
private ConnectivityReceiver mConnectivityReceiver = null;
private WifiReceiver mWifiReceiver = null;
private DownloadReceiver mDownloadReceiver = null;
@@ -118,8 +118,14 @@
initializeNetworkStates();
- mWifiManager.setWifiEnabled(true);
+ }
+
+ /**
+ * Additional initialization needed for wifi related tests.
+ */
+ public void wifiTestInit() {
+ mWifiManager.setWifiEnabled(true);
Log.v(LOG_TAG, "Clear Wifi before we start the test.");
sleep(SHORT_TIMEOUT);
removeConfiguredNetworksAndDisableWifi();
@@ -525,7 +531,7 @@
/**
* Connect to Wi-Fi with the given configuration.
* @param config
- * @return true if we ar connected to a given
+ * @return true if we are connected to a given AP.
*/
public boolean connectToWifiWithConfiguration(WifiConfiguration config) {
// The SSID in the configuration is a pure string, need to convert it to a quoted string.
diff --git a/core/tests/coretests/src/android/widget/focus/RequestFocus.java b/core/tests/coretests/src/android/widget/focus/RequestFocus.java
index 21d762a..af9ee17 100644
--- a/core/tests/coretests/src/android/widget/focus/RequestFocus.java
+++ b/core/tests/coretests/src/android/widget/focus/RequestFocus.java
@@ -21,7 +21,9 @@
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
+import android.widget.LinearLayout;
import android.widget.Button;
+import android.view.View;
/**
* Exercises cases where elements of the UI are requestFocus()ed.
diff --git a/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java b/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java
index baf587e..a78b0c9 100644
--- a/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java
+++ b/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java
@@ -16,27 +16,21 @@
package android.widget.focus;
-import android.os.Handler;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.util.AndroidRuntimeException;
-import android.view.View;
-import android.view.View.OnFocusChangeListener;
-import android.view.ViewTreeObserver.OnGlobalFocusChangeListener;
-import android.widget.Button;
-
+import android.widget.focus.RequestFocus;
import com.android.frameworks.coretests.R;
-import java.util.ArrayList;
-import java.util.List;
+import android.os.Handler;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.Button;
+import android.util.AndroidRuntimeException;
/**
* {@link RequestFocusTest} is set up to exercise cases where the views that
* have focus become invisible or GONE.
*/
-public class RequestFocusTest extends ActivityInstrumentationTestCase2<RequestFocus> {
+public class RequestFocusTest extends ActivityInstrumentationTestCase<RequestFocus> {
private Button mTopLeftButton;
private Button mBottomLeftButton;
@@ -45,7 +39,7 @@
private Handler mHandler;
public RequestFocusTest() {
- super(RequestFocus.class);
+ super("com.android.frameworks.coretests", RequestFocus.class);
}
@Override
@@ -100,145 +94,4 @@
e.getClass().getName());
}
}
-
- /**
- * This tests checks the case in which the first focusable View clears focus.
- * In such a case the framework tries to give the focus to another View starting
- * from the top. Hence, the framework will try to give focus to the view that
- * wants to clear its focus. From a client perspective, the view does not loose
- * focus after the call, therefore no callback for focus change should be invoked.
- *
- * @throws Exception If an error occurs.
- */
- @UiThreadTest
- public void testOnFocusChangeNotCalledIfFocusDoesNotMove() throws Exception {
- // Get the first focusable.
- Button button = mTopLeftButton;
-
- // Make sure that the button is the first focusable and focus it.
- button.getRootView().requestFocus(View.FOCUS_DOWN);
- assertTrue(button.hasFocus());
-
- // Attach on focus change listener that should not be called.
- button.setOnFocusChangeListener(new OnFocusChangeListener() {
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- throw new IllegalStateException("Unexpeced call to"
- + "OnFocusChangeListener#onFocusChange");
- }
- });
-
- // Attach on global focus change listener that should not be called.
- button.getViewTreeObserver().addOnGlobalFocusChangeListener(
- new OnGlobalFocusChangeListener() {
- @Override
- public void onGlobalFocusChanged(View oldFocus, View newFocus) {
- throw new IllegalStateException("Unexpeced call to"
- + "OnFocusChangeListener#onFocusChange");
- }
- });
-
- // Try to clear focus.
- button.clearFocus();
- }
-
- /**
- * This tests check whether the on focus change callbacks are invoked in
- * the proper order when a View loses focus and the framework gives it to
- * the fist focusable one.
- *
- * @throws Exception
- */
- @UiThreadTest
- public void testOnFocusChangeCallbackOrder() throws Exception {
- // Get the first focusable.
- Button clearingFocusButton = mTopRightButton;
- Button gainingFocusButton = mTopLeftButton;
-
- // Make sure that the clearing focus is not the first focusable.
- View focusCandidate = clearingFocusButton.getRootView().getParent().focusSearch(null,
- View.FOCUS_FORWARD);
- assertNotSame("The clearing focus button is not the first focusable.",
- clearingFocusButton, focusCandidate);
- assertSame("The gaining focus button is the first focusable.",
- gainingFocusButton, focusCandidate);
-
- // Focus the clearing focus button.
- clearingFocusButton.requestFocus();
- assertTrue(clearingFocusButton.hasFocus());
-
- // Register the invocation order checker.
- CallbackOrderChecker checker = new CallbackOrderChecker(clearingFocusButton,
- gainingFocusButton);
- clearingFocusButton.setOnFocusChangeListener(checker);
- gainingFocusButton.setOnFocusChangeListener(checker);
- clearingFocusButton.getViewTreeObserver().addOnGlobalFocusChangeListener(checker);
-
- // Try to clear focus.
- clearingFocusButton.clearFocus();
-
- // Check that no callback was invoked since focus did not move.
- checker.verify();
- }
-
- /**
- * This class check whether the focus change callback are invoked in order.
- */
- private class CallbackOrderChecker implements OnFocusChangeListener,
- OnGlobalFocusChangeListener {
-
- private class CallbackInvocation {
- final String mMethodName;
- final Object[] mArguments;
-
- CallbackInvocation(String methodName, Object[] arguments) {
- mMethodName = methodName;
- mArguments = arguments;
- }
- }
-
- private final View mClearingFocusView;
- private final View mGainingFocusView;
-
- private final List<CallbackInvocation> mInvocations = new ArrayList<CallbackInvocation>();
-
- public CallbackOrderChecker(View clearingFocusView, View gainingFocusView) {
- mClearingFocusView = clearingFocusView;
- mGainingFocusView = gainingFocusView;
- }
-
- @Override
- public void onFocusChange(View view, boolean hasFocus) {
- CallbackInvocation invocation = new CallbackInvocation(
- "OnFocusChangeListener#onFocusChange", new Object[] {view, hasFocus});
- mInvocations.add(invocation);
- }
-
- @Override
- public void onGlobalFocusChanged(View oldFocus, View newFocus) {
- CallbackInvocation invocation = new CallbackInvocation(
- "OnFocusChangeListener#onFocusChange", new Object[] {oldFocus, newFocus});
- mInvocations.add(invocation);
- }
-
- public void verify() {
- assertSame("All focus change callback should be invoked.", 3, mInvocations.size());
- assertInvioked("Callback for View clearing focus explected.", 0,
- "OnFocusChangeListener#onFocusChange",
- new Object[] {mClearingFocusView, false});
- assertInvioked("Callback for View global focus change explected.", 1,
- "OnFocusChangeListener#onFocusChange", new Object[] {mClearingFocusView,
- mGainingFocusView});
- assertInvioked("Callback for View gaining focus explected.", 2,
- "OnFocusChangeListener#onFocusChange", new Object[] {mGainingFocusView, true});
- }
-
- private void assertInvioked(String message, int order, String methodName,
- Object[] arguments) {
- CallbackInvocation invocation = mInvocations.get(order);
- assertEquals(message, methodName, invocation.mMethodName);
- assertEquals(message, arguments[0], invocation.mArguments[0]);
- assertEquals(message, arguments[1], invocation.mArguments[1]);
- }
- }
}
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index 02d2f3d..ef38a60 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -51,6 +51,11 @@
$(ALL_MODULES.$(LOCAL_MODULE).INSTALLED) $(font_symlink)
################################
+# On space-constrained devices, we include a subset of fonts:
+ifeq ($(SMALLER_FONT_FOOTPRINT),true)
+droidsans_fallback_src := DroidSansFallback.ttf
+extra_droidsans_fonts := DroidSans.ttf DroidSans-Bold.ttf
+else
include $(CLEAR_VARS)
LOCAL_MODULE := DroidSansEthiopic-Regular.ttf
LOCAL_SRC_FILES := $(LOCAL_MODULE)
@@ -59,15 +64,11 @@
LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts
include $(BUILD_PREBUILT)
-################################
-ifeq ($(SMALLER_FONT_FOOTPRINT),true)
-droidsans_fallback_src := DroidSansFallback.ttf
-extra_droidsans_fonts := DroidSans.ttf DroidSans-Bold.ttf
-else
droidsans_fallback_src := DroidSansFallbackFull.ttf
extra_droidsans_fonts := DroidSans.ttf DroidSans-Bold.ttf DroidSansEthiopic-Regular.ttf
endif # SMALLER_FONT_FOOTPRINT
+################################
include $(CLEAR_VARS)
LOCAL_MODULE := DroidSansFallback.ttf
LOCAL_SRC_FILES := $(droidsans_fallback_src)
@@ -81,3 +82,46 @@
font_symlink :=
droidsans_fallback_src :=
extra_droidsans_fonts :=
+
+################################
+# Build the rest font files as prebuilt.
+
+# $(1): The source file name in LOCAL_PATH.
+# It also serves as the module name and the dest file name.
+define build-one-font-module
+$(eval include $(CLEAR_VARS))\
+$(eval LOCAL_MODULE := $(1))\
+$(eval LOCAL_SRC_FILES := $(1))\
+$(eval LOCAL_MODULE_CLASS := ETC)\
+$(eval LOCAL_MODULE_TAGS := optional)\
+$(eval LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts)\
+$(eval include $(BUILD_PREBUILT))
+endef
+
+font_src_files := \
+ Roboto-Regular.ttf \
+ Roboto-Bold.ttf \
+ Roboto-Italic.ttf \
+ Roboto-BoldItalic.ttf \
+ DroidSansArabic.ttf \
+ DroidNaskh-Regular.ttf \
+ DroidSansHebrew-Regular.ttf \
+ DroidSansHebrew-Bold.ttf \
+ DroidSansThai.ttf \
+ DroidSerif-Regular.ttf \
+ DroidSerif-Bold.ttf \
+ DroidSerif-Italic.ttf \
+ DroidSerif-BoldItalic.ttf \
+ DroidSansMono.ttf \
+ DroidSansArmenian.ttf \
+ DroidSansGeorgian.ttf \
+ AndroidEmoji.ttf \
+ Clockopia.ttf \
+ AndroidClock.ttf \
+ AndroidClock_Highlight.ttf \
+ AndroidClock_Solid.ttf \
+
+$(foreach f, $(font_src_files), $(call build-one-font-module, $(f)))
+
+build-one-font-module :=
+font_src_files :=
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
index 6a9ed53..458f85b 100644
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -14,34 +14,30 @@
# Warning: this is actually a product definition, to be inherited from
-# On space-constrained devices, we include a subset of fonts:
-# First, core/required fonts
PRODUCT_COPY_FILES := \
- frameworks/base/data/fonts/Roboto-Regular.ttf:system/fonts/Roboto-Regular.ttf \
- frameworks/base/data/fonts/Roboto-Bold.ttf:system/fonts/Roboto-Bold.ttf \
- frameworks/base/data/fonts/Roboto-Italic.ttf:system/fonts/Roboto-Italic.ttf \
- frameworks/base/data/fonts/Roboto-BoldItalic.ttf:system/fonts/Roboto-BoldItalic.ttf \
- frameworks/base/data/fonts/DroidSansArabic.ttf:system/fonts/DroidSansArabic.ttf \
- frameworks/base/data/fonts/DroidNaskh-Regular.ttf:system/fonts/DroidNaskh-Regular.ttf \
- frameworks/base/data/fonts/DroidSansHebrew-Regular.ttf:system/fonts/DroidSansHebrew-Regular.ttf \
- frameworks/base/data/fonts/DroidSansHebrew-Bold.ttf:system/fonts/DroidSansHebrew-Bold.ttf \
- frameworks/base/data/fonts/DroidSansThai.ttf:system/fonts/DroidSansThai.ttf \
- frameworks/base/data/fonts/DroidSerif-Regular.ttf:system/fonts/DroidSerif-Regular.ttf \
- frameworks/base/data/fonts/DroidSerif-Bold.ttf:system/fonts/DroidSerif-Bold.ttf \
- frameworks/base/data/fonts/DroidSerif-Italic.ttf:system/fonts/DroidSerif-Italic.ttf \
- frameworks/base/data/fonts/DroidSerif-BoldItalic.ttf:system/fonts/DroidSerif-BoldItalic.ttf \
- frameworks/base/data/fonts/DroidSansMono.ttf:system/fonts/DroidSansMono.ttf \
- frameworks/base/data/fonts/DroidSansArmenian.ttf:system/fonts/DroidSansArmenian.ttf \
- frameworks/base/data/fonts/DroidSansGeorgian.ttf:system/fonts/DroidSansGeorgian.ttf \
- frameworks/base/data/fonts/AndroidEmoji.ttf:system/fonts/AndroidEmoji.ttf \
- frameworks/base/data/fonts/Clockopia.ttf:system/fonts/Clockopia.ttf \
- frameworks/base/data/fonts/AndroidClock.ttf:system/fonts/AndroidClock.ttf \
- frameworks/base/data/fonts/AndroidClock_Highlight.ttf:system/fonts/AndroidClock_Highlight.ttf \
- frameworks/base/data/fonts/AndroidClock_Solid.ttf:system/fonts/AndroidClock_Solid.ttf \
frameworks/base/data/fonts/system_fonts.xml:system/etc/system_fonts.xml \
frameworks/base/data/fonts/fallback_fonts.xml:system/etc/fallback_fonts.xml
-# Next, include additional fonts, depending on how much space we have.
-# Details see module definitions in Android.mk.
PRODUCT_PACKAGES := \
- DroidSansFallback.ttf
+ DroidSansFallback.ttf \
+ Roboto-Regular.ttf \
+ Roboto-Bold.ttf \
+ Roboto-Italic.ttf \
+ Roboto-BoldItalic.ttf \
+ DroidSansArabic.ttf \
+ DroidNaskh-Regular.ttf \
+ DroidSansHebrew-Regular.ttf \
+ DroidSansHebrew-Bold.ttf \
+ DroidSansThai.ttf \
+ DroidSerif-Regular.ttf \
+ DroidSerif-Bold.ttf \
+ DroidSerif-Italic.ttf \
+ DroidSerif-BoldItalic.ttf \
+ DroidSansMono.ttf \
+ DroidSansArmenian.ttf \
+ DroidSansGeorgian.ttf \
+ AndroidEmoji.ttf \
+ Clockopia.ttf \
+ AndroidClock.ttf \
+ AndroidClock_Highlight.ttf \
+ AndroidClock_Solid.ttf \
diff --git a/docs/html/sdk/ndk/index.jd b/docs/html/sdk/ndk/index.jd
index afbad57..29f0749 100644
--- a/docs/html/sdk/ndk/index.jd
+++ b/docs/html/sdk/ndk/index.jd
@@ -1,16 +1,16 @@
ndk=true
-ndk.win_download=android-ndk-r7-windows.zip
-ndk.win_bytes=81270552
-ndk.win_checksum=55483482cf2b75e8dd1a5d9a7caeb6e5
+ndk.win_download=android-ndk-r7b-windows.zip
+ndk.win_bytes=80346206
+ndk.win_checksum=c42b0c9c14428397337421d5e4999380
-ndk.mac_download=android-ndk-r7-darwin-x86.tar.bz2
-ndk.mac_bytes=71262092
-ndk.mac_checksum=817ca5675a1dd44078098e43070f19b6
+ndk.mac_download=android-ndk-r7b-darwin-x86.tar.bz2
+ndk.mac_bytes=73817184
+ndk.mac_checksum=6daa82ca6b73bc0614c9997430079c7a
-ndk.linux_download=android-ndk-r7-linux-x86.tar.bz2
-ndk.linux_bytes=64884365
-ndk.linux_checksum=bf15e6b47bf50824c4b96849bf003ca3
+ndk.linux_download=android-ndk-r7b-linux-x86.tar.bz2
+ndk.linux_bytes=64349733
+ndk.linux_checksum=0eb8af18796cdaa082df8f7c54ad7f9a
page.title=Android NDK
@@ -62,6 +62,116 @@
<div class="toggleable open">
<a href="#" onclick="return toggleDiv(this)"><img src=
"{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px">
+ Android NDK, Revision 7b</a> <em>(February 2012)</em>
+
+ <div class="toggleme">
+ <p>This release of the NDK includes fixes for native Windows builds, Cygwin and many other
+ improvements:</p>
+
+ <dl>
+ <dt>Important bug fixes:</dt>
+
+ <dd>
+ <ul>
+ <li>Updated {@code sys/atomics.h} to avoid correctness issues
+ on some multi-core ARM-based devices. Rebuild your unmodified sources with this
+ version of the NDK and this problem should be completely eliminated.
+ For more details, read {@code docs/ANDROID-ATOMICS.html}.</li>
+ <li>Reverted to {@code binutils} 2.19 to fix debugging issues that
+ appeared in NDK r7 (which switched to {@code binutils} 2.20.1).</li>
+ <li>Fixed {@code ndk-build} on 32-bit Linux. A packaging error put a 64-bit version
+ of the {@code awk} executable under {@code prebuilt/linux-x86/bin} in NDK r7.</li>
+ <li>Fixed native Windows build ({@code ndk-build.cmd}). Other build modes were not
+ affected. The fixes include:
+ <ul>
+ <li>Removed an infinite loop / stack overflow bug that happened when trying
+ to call {@code ndk-build.cmd} from a directory that was <em>not</em> the top of
+ your project path (e.g., in any sub-directory of it).</li>
+ <li>Fixed a problem where the auto-generated dependency files were ignored. This
+ meant that updating a header didn't trigger recompilation of sources that included
+ it.</li>
+ <li>Fixed a problem where special characters in files or paths, other than spaces and
+ quotes, were not correctly handled.</li>
+ </ul>
+ </li>
+ <li>Fixed the standalone toolchain to generate proper binaries when using
+ {@code -lstdc++} (i.e., linking against the GNU {@code libstdc++} C++ runtime). You
+ should use {@code -lgnustl_shared} if you want to link against the shared library
+ version or {@code -lstdc++} for the static version.
+
+ <p>See {@code docs/STANDALONE-TOOLCHAIN.html} for more details about this fix.</p>
+ </li>
+ <li>Fixed {@code gnustl_shared} on Cygwin. The linker complained that it couldn't find
+ {@code libsupc++.a} even though the file was at the right location.</li>
+ <li>Fixed Cygwin C++ link when not using any specific C++ runtime through
+ {@code APP_STL}.</li>
+ </ul>
+ </dd>
+ </dl>
+
+ <dl>
+ <dt>Other changes:</dt>
+
+ <dd>
+ <ul>
+ <li>When your application uses the GNU {@code libstdc++} runtime, the compiler will
+ no longer forcibly enable exceptions and RTTI. This change results in smaller code.
+ <p>If you need these features, you must do one of the following:</p>
+ <ul>
+ <li>Enable exceptions and/or RTTI explicitly in your modules or
+ {@code Application.mk}. (recommended)</li>
+ <li>Define {@code APP_GNUSTL_FORCE_CPP_FEATURES} to {@code 'exceptions'},
+ {@code 'rtti'} or both in your {@code Application.mk}. See
+ {@code docs/APPLICATION-MK.html} for more details.</li>
+ </ul>
+ </li>
+ <li>{@code ndk-gdb} now works properly when your application has private services
+ running in independent processes. It debugs the main application process, instead of the
+ first process listed by {@code ps}, which is usually a service process.</li>
+ <li>Fixed a rare bug where NDK r7 would fail to honor the {@code LOCAL_ARM_MODE} value
+ and always compile certain source files (but not all) to 32-bit instructions.</li>
+ <li>{@code stlport}: Refresh the sources to match the Android platform version. This
+ update fixes a few minor bugs:
+ <ul>
+ <li>Fixed instantiation of an incomplete type</li>
+ <li>Fixed minor "==" versus "=" typo</li>
+ <li>Used {@code memmove} instead of {@code memcpy} in {@code string::assign}</li>
+ <li>Added better handling of {@code IsNANorINF}, {@code IsINF}, {@code IsNegNAN},
+ etc.</li>
+ </ul>
+ <p>For complete details, see the commit log.</p>
+ </li>
+ <li>{@code stlport}: Removed 5 unnecessary static initializers from the library.</li>
+ <li>The GNU libstdc++ libraries for armeabi-v7a were mistakenly compiled for
+ armeabi instead. This change had no impact on correctness, but using the right
+ ABI should provide slightly better performance.</li>
+ <li>The {@code cpu-features} helper library was updated to report three optional
+ x86 CPU features ({@code SSSE3}, {@code MOVBE} and {@code POPCNT}). See
+ {@code docs/CPU-FEATURES.html} for more details.</li>
+ <li>{@code docs/NDK-BUILD.html} was updated to mention {@code NDK_APPLICATION_MK} instead
+ of {@code NDK_APP_APPLICATION_MK} to select a custom {@code Application.mk} file.</li>
+ <li>Cygwin: {@code ndk-build} no longer creates an empty "NUL" file in the current
+ directory when invoked.</li>
+ <li>Cygwin: Added better automatic dependency detection. In the previous version, it
+ didn't work properly in the following cases:
+ <ul>
+ <li>When the Cygwin drive prefix was not {@code /cygdrive}.</li>
+ <li>When using drive-less mounts, for example, when Cygwin would translate
+ {@code /home} to {@code \\server\subdir} instead of {@code C:\Some\Dir}.</li>
+ </ul>
+ </li>
+ <li>Cygwin: {@code ndk-build} does not try to use the native Windows tools under
+ {@code $NDK/prebuilt/windows/bin} with certain versions of Cygwin and/or GNU Make.</li>
+ </ul>
+ </dd>
+ </dl>
+ </div>
+</div>
+
+
+<div class="toggleable closed">
+ <a href="#" onclick="return toggleDiv(this)"><img src=
+ "{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px" width="9px">
Android NDK, Revision 7</a> <em>(November 2011)</em>
<div class="toggleme">
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 0de477a..f7541f7 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -195,7 +195,7 @@
<span style="display:none" class="zh-TW"></span>
</span>
<ul>
- <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r7</a>
+ <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r7b</a>
<span class="new">new!</span>
</li>
<li><a href="<?cs var:toroot ?>sdk/ndk/overview.html">What is the NDK?</a></li>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 380b3d8..6f939be 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -408,16 +408,19 @@
}
/**
- * Creates a new bitmap, scaled from an existing bitmap.
+ * Creates a new bitmap, scaled from an existing bitmap, when possible. If the
+ * specified width and height are the same as the current width and height of
+ * the source btimap, the source bitmap is returned and now new bitmap is
+ * created.
*
* @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.
+ * @return The new scaled bitmap or the source bitmap if no scaling is required.
*/
- public static Bitmap createScaledBitmap(Bitmap src, int dstWidth,
- int dstHeight, boolean filter) {
+ public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight,
+ boolean filter) {
Matrix m;
synchronized (Bitmap.class) {
// small pool of just 1 matrix
@@ -458,14 +461,15 @@
/**
* Returns an immutable bitmap from the specified subset of the source
* bitmap. The new bitmap may be the same object as source, or a copy may
- * have been made. It is
- * initialized with the same density as the original bitmap.
+ * have been made. It is initialized with the same density as the original
+ * bitmap.
*
* @param source The bitmap we are subsetting
* @param x The x coordinate of the first pixel in source
* @param y The y coordinate of the first pixel in source
* @param width The number of pixels in each row
* @param height The number of rows
+ * @return A copy of a subset of the source bitmap or the source bitmap itself.
*/
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height) {
return createBitmap(source, x, y, width, height, null, false);
@@ -473,8 +477,13 @@
/**
* Returns an immutable bitmap from subset of the source bitmap,
- * transformed by the optional matrix. It is
+ * transformed by the optional matrix. The new bitmap may be the
+ * same object as source, or a copy may have been made. It is
* initialized with the same density as the original bitmap.
+ *
+ * If the source bitmap is immutable and the requested subset is the
+ * same as the source bitmap itself, then the source bitmap is
+ * returned and no new bitmap is created.
*
* @param source The bitmap we are subsetting
* @param x The x coordinate of the first pixel in source
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 509b972..44401c8 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2008-2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -131,7 +131,7 @@
public static final int USAGE_GRAPHICS_RENDER_TARGET = 0x0010;
/**
- * USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT The allcation will be
+ * USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT The allocation will be
* used with a SurfaceTexture object. This usage will cause the
* allocation to be created read only.
*
@@ -140,18 +140,18 @@
public static final int USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE = 0x0020;
/**
- * USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT The allcation will be
+ * USAGE_IO_INPUT The allocation will be
* used with a SurfaceTexture object. This usage will cause the
* allocation to be created read only.
*
* @hide
*/
-
public static final int USAGE_IO_INPUT = 0x0040;
+
/**
- * USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT The allcation will be
+ * USAGE_IO_OUTPUT The allocation will be
* used with a SurfaceTexture object. This usage will cause the
- * allocation to be created read only.
+ * allocation to be created write only.
*
* @hide
*/
@@ -921,7 +921,31 @@
if (type.getID() == 0) {
throw new RSInvalidStateException("Bad Type");
}
- int id = rs.nAllocationCreateTyped(type.getID(), mips.mID, usage);
+ int id = rs.nAllocationCreateTyped(type.getID(), mips.mID, usage, 0);
+ if (id == 0) {
+ throw new RSRuntimeException("Allocation creation failed.");
+ }
+ return new Allocation(id, rs, type, usage);
+ }
+
+ /**
+ * @hide
+ * This API is hidden and only intended to be used for
+ * transitional purposes.
+ *
+ * @param type renderscript type describing data layout
+ * @param mips specifies desired mipmap behaviour for the
+ * allocation
+ * @param usage bit field specifying how the allocation is
+ * utilized
+ */
+ static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips,
+ int usage, int pointer) {
+ rs.validate();
+ if (type.getID() == 0) {
+ throw new RSInvalidStateException("Bad Type");
+ }
+ int id = rs.nAllocationCreateTyped(type.getID(), mips.mID, usage, pointer);
if (id == 0) {
throw new RSRuntimeException("Allocation creation failed.");
}
@@ -976,7 +1000,7 @@
b.setX(count);
Type t = b.create();
- int id = rs.nAllocationCreateTyped(t.getID(), MipmapControl.MIPMAP_NONE.mID, usage);
+ int id = rs.nAllocationCreateTyped(t.getID(), MipmapControl.MIPMAP_NONE.mID, usage, 0);
if (id == 0) {
throw new RSRuntimeException("Allocation creation failed.");
}
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index 22ef7bb..f6a0281 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -54,26 +54,59 @@
int[] mArraySizes;
int[] mOffsetInBytes;
+ int[] mVisibleElementMap;
+
DataType mType;
DataKind mKind;
boolean mNormalized;
int mVectorSize;
+ private void updateVisibleSubElements() {
+ if (mElements == null) {
+ return;
+ }
+
+ int noPaddingFieldCount = 0;
+ int fieldCount = mElementNames.length;
+ // Find out how many elements are not padding
+ for (int ct = 0; ct < fieldCount; ct ++) {
+ if (mElementNames[ct].charAt(0) != '#') {
+ noPaddingFieldCount ++;
+ }
+ }
+ mVisibleElementMap = new int[noPaddingFieldCount];
+
+ // Make a map that points us at non-padding elements
+ for (int ct = 0, ctNoPadding = 0; ct < fieldCount; ct ++) {
+ if (mElementNames[ct].charAt(0) != '#') {
+ mVisibleElementMap[ctNoPadding ++] = ct;
+ }
+ }
+ }
+
/**
* @hide
* @return element size in bytes
*/
public int getSizeBytes() {return mSize;}
+ /**
+ * @hide
+ * @return element vector size
+ */
+ public int getVectorSize() {return mVectorSize;}
+
/**
* DataType represents the basic type information for a basic element. The
- * naming convention follows. For numeric types its FLOAT, SIGNED, UNSIGNED
- * followed by the _BITS where BITS is the size of the data. BOOLEAN is a
- * true / false (1,0) represented in an 8 bit container. The UNSIGNED
- * variants with multiple bit definitions are for packed graphical data
- * formats and represents vectors with per vector member sizes which are
- * treated as a single unit for packing and alignment purposes.
+ * naming convention follows. For numeric types it is FLOAT,
+ * SIGNED, or UNSIGNED followed by the _BITS where BITS is the
+ * size of the data. BOOLEAN is a true / false (1,0)
+ * represented in an 8 bit container. The UNSIGNED variants
+ * with multiple bit definitions are for packed graphical data
+ * formats and represent vectors with per vector member sizes
+ * which are treated as a single unit for packing and alignment
+ * purposes.
*
* MATRIX the three matrix types contain FLOAT_32 elements and are treated
* as 32 bits for alignment purposes.
@@ -81,6 +114,11 @@
* RS_* objects. 32 bit opaque handles.
*/
public enum DataType {
+ /**
+ * @hide
+ * new enum
+ */
+ NONE (0, 0),
//FLOAT_16 (1, 2),
FLOAT_32 (2, 4),
FLOAT_64 (3, 8),
@@ -167,10 +205,10 @@
* @return number of sub-elements in this element
*/
public int getSubElementCount() {
- if (mElements == null) {
+ if (mVisibleElementMap == null) {
return 0;
}
- return mElements.length;
+ return mVisibleElementMap.length;
}
/**
@@ -179,13 +217,13 @@
* @return sub-element in this element at given index
*/
public Element getSubElement(int index) {
- if (mElements == null) {
+ if (mVisibleElementMap == null) {
throw new RSIllegalArgumentException("Element contains no sub-elements");
}
- if (index < 0 || index >= mElements.length) {
+ if (index < 0 || index >= mVisibleElementMap.length) {
throw new RSIllegalArgumentException("Illegal sub-element index");
}
- return mElements[index];
+ return mElements[mVisibleElementMap[index]];
}
/**
@@ -194,13 +232,13 @@
* @return sub-element in this element at given index
*/
public String getSubElementName(int index) {
- if (mElements == null) {
+ if (mVisibleElementMap == null) {
throw new RSIllegalArgumentException("Element contains no sub-elements");
}
- if (index < 0 || index >= mElements.length) {
+ if (index < 0 || index >= mVisibleElementMap.length) {
throw new RSIllegalArgumentException("Illegal sub-element index");
}
- return mElementNames[index];
+ return mElementNames[mVisibleElementMap[index]];
}
/**
@@ -209,13 +247,13 @@
* @return array size of sub-element in this element at given index
*/
public int getSubElementArraySize(int index) {
- if (mElements == null) {
+ if (mVisibleElementMap == null) {
throw new RSIllegalArgumentException("Element contains no sub-elements");
}
- if (index < 0 || index >= mElements.length) {
+ if (index < 0 || index >= mVisibleElementMap.length) {
throw new RSIllegalArgumentException("Illegal sub-element index");
}
- return mArraySizes[index];
+ return mArraySizes[mVisibleElementMap[index]];
}
/**
@@ -224,13 +262,29 @@
* @return offset in bytes of sub-element in this element at given index
*/
public int getSubElementOffsetBytes(int index) {
- if (mElements == null) {
+ if (mVisibleElementMap == null) {
throw new RSIllegalArgumentException("Element contains no sub-elements");
}
- if (index < 0 || index >= mElements.length) {
+ if (index < 0 || index >= mVisibleElementMap.length) {
throw new RSIllegalArgumentException("Illegal sub-element index");
}
- return mOffsetInBytes[index];
+ return mOffsetInBytes[mVisibleElementMap[index]];
+ }
+
+ /**
+ * @hide
+ * @return element data type
+ */
+ public DataType getDataType() {
+ return mType;
+ }
+
+ /**
+ * @hide
+ * @return element data kind
+ */
+ public DataKind getDataKind() {
+ return mKind;
}
/**
@@ -681,14 +735,18 @@
Element(int id, RenderScript rs, Element[] e, String[] n, int[] as) {
super(id, rs);
mSize = 0;
+ mVectorSize = 1;
mElements = e;
mElementNames = n;
mArraySizes = as;
+ mType = DataType.NONE;
+ mKind = DataKind.USER;
mOffsetInBytes = new int[mElements.length];
for (int ct = 0; ct < mElements.length; ct++ ) {
mOffsetInBytes[ct] = mSize;
mSize += mElements[ct].mSize * mArraySizes[ct];
}
+ updateVisibleSubElements();
}
Element(int id, RenderScript rs, DataType dt, DataKind dk, boolean norm, int size) {
@@ -753,7 +811,7 @@
mSize += mElements[i].mSize * mArraySizes[i];
}
}
-
+ updateVisibleSubElements();
}
/**
diff --git a/graphics/java/android/renderscript/Path.java b/graphics/java/android/renderscript/Path.java
new file mode 100644
index 0000000..83ae150
--- /dev/null
+++ b/graphics/java/android/renderscript/Path.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import java.util.Vector;
+import android.util.Log;
+
+/**
+ * @hide
+ *
+ */
+public class Path extends BaseObj {
+
+ public enum Primitive {
+ QUADRATIC_BEZIER(0),
+ CUBIC_BEZIER(1);
+
+ int mID;
+ Primitive(int id) {
+ mID = id;
+ }
+ }
+
+ Allocation mVertexBuffer;
+ Allocation mLoopBuffer;
+ Primitive mPrimitive;
+ float mQuality;
+ boolean mCoverageToAlpha;
+
+ Path(int id, RenderScript rs, Primitive p, Allocation vtx, Allocation loop, float q) {
+ super(id, rs);
+ mVertexBuffer = vtx;
+ mLoopBuffer = loop;
+ mPrimitive = p;
+ mQuality = q;
+ }
+
+ public Allocation getVertexAllocation() {
+ return mVertexBuffer;
+ }
+
+ public Allocation getLoopAllocation() {
+ return mLoopBuffer;
+ }
+
+ public Primitive getPrimitive() {
+ return mPrimitive;
+ }
+
+ @Override
+ void updateFromNative() {
+ }
+
+
+ public static Path createStaticPath(RenderScript rs, Primitive p, float quality, Allocation vtx) {
+ int id = rs.nPathCreate(p.mID, false, vtx.getID(), 0, quality);
+ Path newPath = new Path(id, rs, p, null, null, quality);
+ return newPath;
+ }
+
+ public static Path createStaticPath(RenderScript rs, Primitive p, float quality, Allocation vtx, Allocation loops) {
+ return null;
+ }
+
+ public static Path createDynamicPath(RenderScript rs, Primitive p, float quality, Allocation vtx) {
+ return null;
+ }
+
+ public static Path createDynamicPath(RenderScript rs, Primitive p, float quality, Allocation vtx, Allocation loops) {
+ return null;
+ }
+
+
+}
+
+
diff --git a/graphics/java/android/renderscript/Program.java b/graphics/java/android/renderscript/Program.java
index a1b1ba3..3f769ee 100644
--- a/graphics/java/android/renderscript/Program.java
+++ b/graphics/java/android/renderscript/Program.java
@@ -77,6 +77,40 @@
}
/**
+ * @hide
+ */
+ public int getConstantCount() {
+ return mConstants != null ? mConstants.length : 0;
+ }
+
+ /**
+ * @hide
+ */
+ public Type getConstant(int slot) {
+ if (slot < 0 || slot >= mConstants.length) {
+ throw new IllegalArgumentException("Slot ID out of range.");
+ }
+ return mConstants[slot];
+ }
+
+ /**
+ * @hide
+ */
+ public int getTextureCount() {
+ return mTextureCount;
+ }
+
+ /**
+ * @hide
+ */
+ public TextureType getTextureType(int slot) {
+ if ((slot < 0) || (slot >= mTextureCount)) {
+ throw new IllegalArgumentException("Slot ID out of range.");
+ }
+ return mTextures[slot];
+ }
+
+ /**
* Binds a constant buffer to be used as uniform inputs to the
* program
*
diff --git a/graphics/java/android/renderscript/ProgramVertex.java b/graphics/java/android/renderscript/ProgramVertex.java
index 56bb836..b3c1bd9 100644
--- a/graphics/java/android/renderscript/ProgramVertex.java
+++ b/graphics/java/android/renderscript/ProgramVertex.java
@@ -55,6 +55,23 @@
}
/**
+ * @hide
+ */
+ public int getInputCount() {
+ return mInputs != null ? mInputs.length : 0;
+ }
+
+ /**
+ * @hide
+ */
+ public Element getInput(int slot) {
+ if (slot < 0 || slot >= mInputs.length) {
+ throw new IllegalArgumentException("Slot ID out of range.");
+ }
+ return mInputs[slot];
+ }
+
+ /**
* Builder class for creating ProgramVertex objects.
* The builder starts empty and the user must minimally provide
* the GLSL shader code, and the varying inputs. Constant, or
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 3f3033b..d3c801f2 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -231,10 +231,10 @@
rsnTypeGetNativeData(mContext, id, typeData);
}
- native int rsnAllocationCreateTyped(int con, int type, int mip, int usage);
- synchronized int nAllocationCreateTyped(int type, int mip, int usage) {
+ native int rsnAllocationCreateTyped(int con, int type, int mip, int usage, int pointer);
+ synchronized int nAllocationCreateTyped(int type, int mip, int usage, int pointer) {
validate();
- return rsnAllocationCreateTyped(mContext, type, mip, usage);
+ return rsnAllocationCreateTyped(mContext, type, mip, usage, pointer);
}
native int rsnAllocationCreateFromBitmap(int con, int type, int mip, Bitmap bmp, int usage);
synchronized int nAllocationCreateFromBitmap(int type, int mip, Bitmap bmp, int usage) {
@@ -590,6 +590,11 @@
rsnMeshGetIndices(mContext, id, idxIds, primitives, vtxIdCount);
}
+ native int rsnPathCreate(int con, int prim, boolean isStatic, int vtx, int loop, float q);
+ synchronized int nPathCreate(int prim, boolean isStatic, int vtx, int loop, float q) {
+ validate();
+ return rsnPathCreate(mContext, prim, isStatic, vtx, loop, q);
+ }
int mDev;
int mContext;
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index a9f0f1f..94f19b3 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -430,10 +430,10 @@
// -----------------------------------
static jint
-nAllocationCreateTyped(JNIEnv *_env, jobject _this, RsContext con, jint type, jint mips, jint usage)
+nAllocationCreateTyped(JNIEnv *_env, jobject _this, RsContext con, jint type, jint mips, jint usage, jint pointer)
{
- LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i)", con, (RsElement)type, mips, usage);
- return (jint) rsAllocationCreateTyped(con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage);
+ LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)", con, (RsElement)type, mips, usage, (void *)pointer);
+ return (jint) rsAllocationCreateTyped(con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage, (uint32_t)pointer);
}
static void
@@ -1129,6 +1129,17 @@
// ---------------------------------------------------------------------------
+//native int rsnPathCreate(int con, int prim, boolean isStatic, int vtx, int loop, float q);
+static jint
+nPathCreate(JNIEnv *_env, jobject _this, RsContext con, jint prim, jboolean isStatic, jint _vtx, jint _loop, jfloat q) {
+ LOG_API("nPathCreate, con(%p)", con);
+
+ int id = (int)rsPathCreate(con, (RsPathPrimitive)prim, isStatic,
+ (RsAllocation)_vtx,
+ (RsAllocation)_loop, q);
+ return id;
+}
+
static jint
nMeshCreate(JNIEnv *_env, jobject _this, RsContext con, jintArray _vtx, jintArray _idx, jintArray _prim)
{
@@ -1257,7 +1268,7 @@
{"rsnTypeCreate", "(IIIIIZZ)I", (void*)nTypeCreate },
{"rsnTypeGetNativeData", "(II[I)V", (void*)nTypeGetNativeData },
-{"rsnAllocationCreateTyped", "(IIII)I", (void*)nAllocationCreateTyped },
+{"rsnAllocationCreateTyped", "(IIIII)I", (void*)nAllocationCreateTyped },
{"rsnAllocationCreateFromBitmap", "(IIILandroid/graphics/Bitmap;I)I", (void*)nAllocationCreateFromBitmap },
{"rsnAllocationCubeCreateFromBitmap","(IIILandroid/graphics/Bitmap;I)I", (void*)nAllocationCubeCreateFromBitmap },
@@ -1318,6 +1329,7 @@
{"rsnSamplerCreate", "(IIIIIIF)I", (void*)nSamplerCreate },
+{"rsnPathCreate", "(IIZIIF)I", (void*)nPathCreate },
{"rsnMeshCreate", "(I[I[I[I)I", (void*)nMeshCreate },
{"rsnMeshGetVertexBufferCount", "(II)I", (void*)nMeshGetVertexBufferCount },
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 991a181..ae99160 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -60,6 +60,8 @@
BufferQueue(bool allowSynchronousMode = true);
virtual ~BufferQueue();
+ virtual int query(int what, int* value);
+
// setBufferCount updates the number of available buffer slots. After
// calling this all buffer slots are both unallocated and owned by the
// BufferQueue object (i.e. they are not owned by the client).
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 4318f0f..dcab049 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -55,7 +55,7 @@
virtual ~SurfaceTexture();
- virtual int query(int what, int* value);
+
// updateTexImage sets the image contents of the target texture to that of
// the most recently queued buffer.
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index ca57f9e..437a89c 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -341,7 +341,7 @@
private:
friend class AudioRecord;
virtual bool threadLoop();
- virtual status_t readyToRun() { return NO_ERROR; }
+ virtual status_t readyToRun();
virtual void onFirstRef() {}
AudioRecord& mReceiver;
};
@@ -359,7 +359,9 @@
sp<IAudioRecord> mAudioRecord;
sp<IMemory> mCblkMemory;
sp<ClientRecordThread> mClientRecordThread;
+ status_t mReadyToRun;
Mutex mLock;
+ Condition mCondition;
uint32_t mFrameCount;
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index da99620..1916ac5 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -131,7 +131,7 @@
NUM_CONFIG_EVENTS
};
- // audio output descritor used to cache output configurations in client process to avoid frequent calls
+ // audio output descriptor used to cache output configurations in client process to avoid frequent calls
// through IAudioFlinger
class OutputDescriptor {
public:
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 11db81b..ac7f6cf 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -58,8 +58,8 @@
EVENT_BUFFER_END = 5 // Playback head is at the end of the buffer.
};
- /* Create Buffer on the stack and pass it to obtainBuffer()
- * and releaseBuffer().
+ /* Client should declare Buffer on the stack and pass address to obtainBuffer()
+ * and releaseBuffer(). See also callback_t for EVENT_MORE_DATA.
*/
class Buffer
@@ -68,12 +68,16 @@
enum {
MUTE = 0x00000001
};
- uint32_t flags;
+ uint32_t flags; // 0 or MUTE
audio_format_t format; // but AUDIO_FORMAT_PCM_8_BIT -> AUDIO_FORMAT_PCM_16_BIT
// accessed directly by WebKit ANP callback
int channelCount; // will be removed in the future, do not use
- size_t frameCount;
- size_t size;
+
+ size_t frameCount; // number of sample frames corresponding to size;
+ // on input it is the number of frames desired,
+ // on output is the number of frames actually filled
+
+ size_t size; // input/output in byte units
union {
void* raw;
short* i16; // signed 16-bit
@@ -84,15 +88,15 @@
/* As a convenience, if a callback is supplied, a handler thread
* is automatically created with the appropriate priority. This thread
- * invokes the callback when a new buffer becomes available or an underrun condition occurs.
+ * invokes the callback when a new buffer becomes available or various conditions occur.
* Parameters:
*
* event: type of event notified (see enum AudioTrack::event_type).
* user: Pointer to context for use by the callback receiver.
* info: Pointer to optional parameter according to event type:
* - EVENT_MORE_DATA: pointer to AudioTrack::Buffer struct. The callback must not write
- * more bytes than indicated by 'size' field and update 'size' if less bytes are
- * written.
+ * more bytes than indicated by 'size' field and update 'size' if fewer bytes are
+ * written.
* - EVENT_UNDERRUN: unused.
* - EVENT_LOOP_END: pointer to an int indicating the number of loops remaining.
* - EVENT_MARKER: pointer to an uint32_t containing the marker position in frames.
@@ -225,7 +229,7 @@
*/
uint32_t latency() const;
- /* getters, see constructor */
+ /* getters, see constructors and set() */
audio_stream_type_t streamType() const;
audio_format_t format() const;
@@ -299,7 +303,6 @@
* (loopEnd-loopStart) <= framecount()
*/
status_t setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount);
- status_t getLoop(uint32_t *loopStart, uint32_t *loopEnd, int *loopCount) const;
/* Sets marker position. When playback reaches the number of frames specified, a callback with
* event type EVENT_MARKER is called. Calling setMarkerPosition with marker == 0 cancels marker
@@ -401,13 +404,19 @@
status_t attachAuxEffect(int effectId);
/* Obtains a buffer of "frameCount" frames. The buffer must be
- * filled entirely. If the track is stopped, obtainBuffer() returns
+ * filled entirely, and then released with releaseBuffer().
+ * If the track is stopped, obtainBuffer() returns
* STOPPED instead of NO_ERROR as long as there are buffers available,
* at which point NO_MORE_BUFFERS is returned.
* Buffers will be returned until the pool (buffercount())
* is exhausted, at which point obtainBuffer() will either block
* or return WOULD_BLOCK depending on the value of the "blocking"
* parameter.
+ *
+ * Interpretation of waitCount:
+ * +n limits wait time to n * WAIT_PERIOD_MS,
+ * -1 causes an (almost) infinite wait time,
+ * 0 non-blocking.
*/
enum {
@@ -416,12 +425,19 @@
};
status_t obtainBuffer(Buffer* audioBuffer, int32_t waitCount);
+
+ /* Release a filled buffer of "frameCount" frames for AudioFlinger to process. */
void releaseBuffer(Buffer* audioBuffer);
/* As a convenience we provide a write() interface to the audio buffer.
- * This is implemented on top of lockBuffer/unlockBuffer. For best
- * performance use callbacks. Return actual number of bytes written.
- *
+ * This is implemented on top of obtainBuffer/releaseBuffer. For best
+ * performance use callbacks. Returns actual number of bytes written >= 0,
+ * or one of the following negative status codes:
+ * INVALID_OPERATION AudioTrack is configured for shared buffer mode
+ * BAD_VALUE size is invalid
+ * STOPPED AudioTrack was stopped during the write
+ * NO_MORE_BUFFERS when obtainBuffer() returns same
+ * or any other error code returned by IAudioTrack::start() or restoreTrack_l().
*/
ssize_t write(const void* buffer, size_t size);
@@ -448,6 +464,7 @@
AudioTrack& mReceiver;
};
+ // body of AudioTrackThread::threadLoop()
bool processAudioBuffer(const sp<AudioTrackThread>& thread);
status_t createTrack_l(audio_stream_type_t streamType,
uint32_t sampleRate,
@@ -484,7 +501,7 @@
bool mActive; // protected by mLock
- callback_t mCbf;
+ callback_t mCbf; // callback handler for events, or NULL
void* mUserData;
uint32_t mNotificationFramesReq; // requested number of frames between each notification callback
uint32_t mNotificationFramesAct; // actual number of frames between each notification callback
diff --git a/include/media/EffectsFactoryApi.h b/include/media/EffectsFactoryApi.h
index df83995..65c26f47 100644
--- a/include/media/EffectsFactoryApi.h
+++ b/include/media/EffectsFactoryApi.h
@@ -87,7 +87,7 @@
// Description: Creates an effect engine of the specified type and returns an
// effect control interface on this engine. The function will allocate the
// resources for an instance of the requested effect engine and return
-// a handler on the effect control interface.
+// a handle on the effect control interface.
//
// Input:
// pEffectUuid: pointer to the effect uuid.
@@ -115,17 +115,17 @@
//
// Function: EffectRelease
//
-// Description: Releases the effect engine whose handler is given as argument.
+// Description: Releases the effect engine whose handle is given as argument.
// All resources allocated to this particular instance of the effect are
// released.
//
// Input:
-// handle: handler on the effect interface to be released.
+// handle: handle on the effect interface to be released.
//
// Output:
// returned value: 0 successful operation.
// -ENODEV factory failed to initialize
-// -EINVAL invalid interface handler
+// -EINVAL invalid interface handle
//
////////////////////////////////////////////////////////////////////////////////
int EffectRelease(effect_handle_t handle);
diff --git a/include/media/IAudioRecord.h b/include/media/IAudioRecord.h
index 46735de..7869020 100644
--- a/include/media/IAudioRecord.h
+++ b/include/media/IAudioRecord.h
@@ -37,8 +37,9 @@
/* After it's created the track is not active. Call start() to
* make it active. If set, the callback will start being called.
+ * tid identifies the client callback thread, or 0 if not needed.
*/
- virtual status_t start() = 0;
+ virtual status_t start(pid_t tid) = 0;
/* Stop a track. If set, the callback will cease being called and
* obtainBuffer will return an error. Buffers that are already released
diff --git a/include/media/IAudioTrack.h b/include/media/IAudioTrack.h
index b83e552..e4772a1 100644
--- a/include/media/IAudioTrack.h
+++ b/include/media/IAudioTrack.h
@@ -40,17 +40,18 @@
/* After it's created the track is not active. Call start() to
* make it active. If set, the callback will start being called.
+ * tid identifies the client callback thread, or 0 if not needed.
*/
- virtual status_t start() = 0;
+ virtual status_t start(pid_t tid) = 0;
/* Stop a track. If set, the callback will cease being called and
* obtainBuffer will return an error. Buffers that are already released
- * will be processed, unless flush() is called.
+ * will continue to be processed, unless/until flush() is called.
*/
virtual void stop() = 0;
- /* Flush a stopped track. All pending buffers are discarded.
- * This function has no effect if the track is not stopped.
+ /* Flush a stopped or paused track. All pending/released buffers are discarded.
+ * This function has no effect if the track is not stopped or paused.
*/
virtual void flush() = 0;
@@ -61,7 +62,7 @@
/* Pause a track. If set, the callback will cease being called and
* obtainBuffer will return an error. Buffers that are already released
- * will be processed, unless flush() is called.
+ * will continue to be processed, unless/until flush() is called.
*/
virtual void pause() = 0;
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 7beb176..77c82b2 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -96,6 +96,8 @@
virtual void flush() = 0;
virtual void pause() = 0;
virtual void close() = 0;
+
+ virtual status_t setPlaybackRatePermille(int32_t rate) { return INVALID_OPERATION; }
};
MediaPlayerBase() : mCookie(0), mNotify(0) {}
diff --git a/include/media/MemoryLeakTrackUtil.h b/include/media/MemoryLeakTrackUtil.h
index 290b748..ac0f6b2 100644
--- a/include/media/MemoryLeakTrackUtil.h
+++ b/include/media/MemoryLeakTrackUtil.h
@@ -19,7 +19,7 @@
namespace android {
/*
- * Dump the memory adddress of the calling process to the given fd.
+ * Dump the memory address of the calling process to the given fd.
*/
extern void dumpMemoryAddresses(int fd);
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 00b7dd5..d0b87c8 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -145,6 +145,9 @@
// audio track, or zero for error (e.g. no audio track) or unknown.
KEY_PARAMETER_AUDIO_CHANNEL_COUNT = 1200, // get only
+ // Playback rate expressed in permille (1000 is normal speed), saved as int32_t, with negative
+ // values used for rewinding or reverse playback.
+ KEY_PARAMETER_PLAYBACK_RATE_PERMILLE = 1300, // set only
};
// ----------------------------------------------------------------------------
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
index 0b79324..70c47ae 100644
--- a/include/media/stagefright/AudioPlayer.h
+++ b/include/media/stagefright/AudioPlayer.h
@@ -64,6 +64,8 @@
bool isSeeking();
bool reachedEOS(status_t *finalStatus);
+ status_t setPlaybackRatePermille(int32_t ratePermille);
+
private:
friend class VideoEditorAudioPlayer;
sp<MediaSource> mSource;
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 23226c0..af2db93 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -62,16 +62,23 @@
// are in the same line of data cache.
Mutex lock; // sizeof(int)
Condition cv; // sizeof(int)
+
+ // next 4 are offsets within "buffers"
volatile uint32_t user;
volatile uint32_t server;
uint32_t userBase;
uint32_t serverBase;
+
+ // if there is a shared buffer, "buffers" is the value of pointer() for the shared
+ // buffer, otherwise "buffers" points immediately after the control block
void* buffers;
uint32_t frameCount;
+
// Cache line boundary
+
uint32_t loopStart;
- uint32_t loopEnd;
- int loopCount;
+ uint32_t loopEnd; // read-only for server, read/write for client
+ int loopCount; // read/write for client
// Channel volumes are fixed point U4.12, so 0x1000 means 1.0.
// Left channel is in [0:15], right channel is in [16:31].
@@ -82,29 +89,39 @@
public:
uint32_t sampleRate;
+
// NOTE: audio_track_cblk_t::frameSize is not equal to AudioTrack::frameSize() for
// 8 bit PCM data: in this case, mCblk->frameSize is based on a sample size of
// 16 bit because data is converted to 16 bit before being stored in buffer
+ // read-only for client, server writes once at initialization and is then read-only
uint8_t frameSize; // would normally be size_t, but 8 bits is plenty
+
+ // never used
uint8_t pad1;
+
+ // used by client only
uint16_t bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger
- uint16_t waitTimeMs; // Cumulated wait time
+ uint16_t waitTimeMs; // Cumulated wait time, used by client only
private:
+ // client write-only, server read-only
uint16_t mSendLevel; // Fixed point U4.12 so 0x1000 means 1.0
public:
volatile int32_t flags;
// Cache line boundary (32 bytes)
+ // Since the control block is always located in shared memory, this constructor
+ // is only used for placement new(). It is never used for regular new() or stack.
audio_track_cblk_t();
- uint32_t stepUser(uint32_t frameCount);
- bool stepServer(uint32_t frameCount);
+ uint32_t stepUser(uint32_t frameCount); // called by client only, where
+ // client includes regular AudioTrack and AudioFlinger::PlaybackThread::OutputTrack
+ bool stepServer(uint32_t frameCount); // called by server only
void* buffer(uint32_t offset) const;
uint32_t framesAvailable();
uint32_t framesAvailable_l();
- uint32_t framesReady();
+ uint32_t framesReady(); // called by server only
bool tryLock();
// No barriers on the following operations, so the ordering of loads/stores
diff --git a/include/utils/KeyedVector.h b/include/utils/KeyedVector.h
index 6bcdea4..fcc3bcf 100644
--- a/include/utils/KeyedVector.h
+++ b/include/utils/KeyedVector.h
@@ -66,7 +66,7 @@
ssize_t indexOfKey(const KEY& key) const;
/*!
- * modifing the array
+ * modifying the array
*/
VALUE& editValueFor(const KEY& key);
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index c7e2c0f..0791de2 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -166,6 +166,37 @@
return OK;
}
+int BufferQueue::query(int what, int* outValue)
+{
+ Mutex::Autolock lock(mMutex);
+
+ if (mAbandoned) {
+ ST_LOGE("query: SurfaceTexture has been abandoned!");
+ return NO_INIT;
+ }
+
+ int value;
+ switch (what) {
+ case NATIVE_WINDOW_WIDTH:
+ value = mDefaultWidth;
+ break;
+ case NATIVE_WINDOW_HEIGHT:
+ value = mDefaultHeight;
+ break;
+ case NATIVE_WINDOW_FORMAT:
+ value = mPixelFormat;
+ break;
+ case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
+ value = mSynchronousMode ?
+ (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
+ break;
+ default:
+ return BAD_VALUE;
+ }
+ outValue[0] = value;
+ return NO_ERROR;
+}
+
status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
ST_LOGV("requestBuffer: slot=%d", slot);
Mutex::Autolock lock(mMutex);
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index be1bcd1..a7bfc61 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -416,36 +416,7 @@
return mSynchronousMode;
}
-int SurfaceTexture::query(int what, int* outValue)
-{
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ST_LOGE("query: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
-
- int value;
- switch (what) {
- case NATIVE_WINDOW_WIDTH:
- value = mDefaultWidth;
- break;
- case NATIVE_WINDOW_HEIGHT:
- value = mDefaultHeight;
- break;
- case NATIVE_WINDOW_FORMAT:
- value = mPixelFormat;
- break;
- case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
- value = mSynchronousMode ?
- (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
- break;
- default:
- return BAD_VALUE;
- }
- outValue[0] = value;
- return NO_ERROR;
-}
void SurfaceTexture::abandon() {
Mutex::Autolock lock(mMutex);
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index 2166ce7..9c5d06b 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -95,6 +95,7 @@
rsMatrix4x4.cpp \
rsMesh.cpp \
rsMutex.cpp \
+ rsPath.cpp \
rsProgram.cpp \
rsProgramFragment.cpp \
rsProgramStore.cpp \
@@ -117,6 +118,7 @@
driver/rsdGL.cpp \
driver/rsdMesh.cpp \
driver/rsdMeshObj.cpp \
+ driver/rsdPath.cpp \
driver/rsdProgram.cpp \
driver/rsdProgramRaster.cpp \
driver/rsdProgramStore.cpp \
@@ -201,6 +203,7 @@
rsMatrix4x4.cpp \
rsMesh.cpp \
rsMutex.cpp \
+ rsPath.cpp \
rsProgram.cpp \
rsProgramFragment.cpp \
rsProgramStore.cpp \
diff --git a/libs/rs/RenderScriptDefines.h b/libs/rs/RenderScriptDefines.h
index 5b0a3da..990ef26 100644
--- a/libs/rs/RenderScriptDefines.h
+++ b/libs/rs/RenderScriptDefines.h
@@ -41,6 +41,7 @@
typedef void * RsSampler;
typedef void * RsScript;
typedef void * RsMesh;
+typedef void * RsPath;
typedef void * RsType;
typedef void * RsObjectBase;
@@ -155,6 +156,8 @@
RS_TYPE_PROGRAM_VERTEX,
RS_TYPE_PROGRAM_RASTER,
RS_TYPE_PROGRAM_STORE,
+
+ RS_TYPE_INVALID = 10000,
};
enum RsDataKind {
@@ -166,6 +169,8 @@
RS_KIND_PIXEL_RGB,
RS_KIND_PIXEL_RGBA,
RS_KIND_PIXEL_DEPTH,
+
+ RS_KIND_INVALID = 100,
};
enum RsSamplerParam {
@@ -184,6 +189,8 @@
RS_SAMPLER_WRAP,
RS_SAMPLER_CLAMP,
RS_SAMPLER_LINEAR_MIP_NEAREST,
+
+ RS_SAMPLER_INVALID = 100,
};
enum RsTextureTarget {
@@ -224,7 +231,8 @@
RS_BLEND_SRC_ONE_MINUS_SRC_ALPHA, // 5
RS_BLEND_SRC_DST_ALPHA, // 6
RS_BLEND_SRC_ONE_MINUS_DST_ALPHA, // 7
- RS_BLEND_SRC_SRC_ALPHA_SATURATE // 8
+ RS_BLEND_SRC_SRC_ALPHA_SATURATE, // 8
+ RS_BLEND_SRC_INVALID = 100,
};
enum RsBlendDstFunc {
@@ -235,7 +243,9 @@
RS_BLEND_DST_SRC_ALPHA, // 4
RS_BLEND_DST_ONE_MINUS_SRC_ALPHA, // 5
RS_BLEND_DST_DST_ALPHA, // 6
- RS_BLEND_DST_ONE_MINUS_DST_ALPHA // 7
+ RS_BLEND_DST_ONE_MINUS_DST_ALPHA, // 7
+
+ RS_BLEND_DST_INVALID = 100,
};
enum RsTexEnvMode {
@@ -258,7 +268,14 @@
RS_PRIMITIVE_LINE_STRIP,
RS_PRIMITIVE_TRIANGLE,
RS_PRIMITIVE_TRIANGLE_STRIP,
- RS_PRIMITIVE_TRIANGLE_FAN
+ RS_PRIMITIVE_TRIANGLE_FAN,
+
+ RS_PRIMITIVE_INVALID = 100,
+};
+
+enum RsPathPrimitive {
+ RS_PATH_PRIMITIVE_QUADRATIC_BEZIER,
+ RS_PATH_PRIMITIVE_CUBIC_BEZIER
};
enum RsError {
@@ -312,7 +329,8 @@
enum RsCullMode {
RS_CULL_BACK,
RS_CULL_FRONT,
- RS_CULL_NONE
+ RS_CULL_NONE,
+ RS_CULL_INVALID = 100,
};
typedef struct {
diff --git a/libs/rs/driver/rsdAllocation.cpp b/libs/rs/driver/rsdAllocation.cpp
index fac40f2..ea92192 100644
--- a/libs/rs/driver/rsdAllocation.cpp
+++ b/libs/rs/driver/rsdAllocation.cpp
@@ -219,10 +219,13 @@
return false;
}
- void * ptr = malloc(alloc->mHal.state.type->getSizeBytes());
+ void * ptr = alloc->mHal.state.usrPtr;
if (!ptr) {
- free(drv);
- return false;
+ ptr = malloc(alloc->mHal.state.type->getSizeBytes());
+ if (!ptr) {
+ free(drv);
+ return false;
+ }
}
drv->glTarget = GL_NONE;
@@ -276,7 +279,7 @@
drv->renderTargetID = 0;
}
- if (drv->mallocPtr) {
+ if (drv->mallocPtr && !alloc->mHal.state.usrPtr) {
free(drv->mallocPtr);
drv->mallocPtr = NULL;
}
diff --git a/libs/rs/driver/rsdCore.cpp b/libs/rs/driver/rsdCore.cpp
index 9987027..e011955 100644
--- a/libs/rs/driver/rsdCore.cpp
+++ b/libs/rs/driver/rsdCore.cpp
@@ -18,6 +18,7 @@
#include "rsdAllocation.h"
#include "rsdBcc.h"
#include "rsdGL.h"
+#include "rsdPath.h"
#include "rsdProgramStore.h"
#include "rsdProgramRaster.h"
#include "rsdProgramVertex.h"
@@ -115,6 +116,13 @@
},
{
+ rsdPathInitStatic,
+ rsdPathInitDynamic,
+ rsdPathDraw,
+ rsdPathDestroy
+ },
+
+ {
rsdSamplerInit,
rsdSamplerDestroy
},
@@ -260,6 +268,9 @@
for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) {
setpriority(PRIO_PROCESS, dc->mWorkers.mNativeThreadId[ct], priority);
}
+ if (dc->mHasGraphics) {
+ rsdGLSetPriority(rsc, priority);
+ }
}
void Shutdown(Context *rsc) {
diff --git a/libs/rs/driver/rsdCore.h b/libs/rs/driver/rsdCore.h
index 126c87a..168bdf3 100644
--- a/libs/rs/driver/rsdCore.h
+++ b/libs/rs/driver/rsdCore.h
@@ -41,6 +41,7 @@
typedef struct RsdHalRec {
uint32_t version_major;
uint32_t version_minor;
+ bool mHasGraphics;
struct Workers {
volatile int mRunningCount;
diff --git a/libs/rs/driver/rsdGL.cpp b/libs/rs/driver/rsdGL.cpp
index 368dd710..b136cc7 100644
--- a/libs/rs/driver/rsdGL.cpp
+++ b/libs/rs/driver/rsdGL.cpp
@@ -361,6 +361,7 @@
dc->gl.vertexArrayState = new RsdVertexArrayState();
dc->gl.vertexArrayState->init(dc->gl.gl.maxVertexAttribs);
dc->gl.currentFrameBuffer = NULL;
+ dc->mHasGraphics = true;
ALOGV("%p initGLThread end", rsc);
rsc->setWatchdogGL(NULL, 0, NULL);
@@ -421,6 +422,15 @@
RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface);
}
+void rsdGLSetPriority(const Context *rsc, int32_t priority) {
+ if (priority > 0) {
+ // Mark context as low priority.
+ ALOGV("low pri");
+ } else {
+ ALOGV("normal pri");
+ }
+}
+
void rsdGLCheckError(const android::renderscript::Context *rsc,
const char *msg, bool isFatal) {
GLenum err = glGetError();
diff --git a/libs/rs/driver/rsdGL.h b/libs/rs/driver/rsdGL.h
index 51893c3..e015cb1 100644
--- a/libs/rs/driver/rsdGL.h
+++ b/libs/rs/driver/rsdGL.h
@@ -82,6 +82,8 @@
void rsdGLSwap(const android::renderscript::Context *rsc);
void rsdGLCheckError(const android::renderscript::Context *rsc,
const char *msg, bool isFatal = false);
+void rsdGLSetPriority(const android::renderscript::Context *rsc,
+ int32_t priority);
#endif
diff --git a/libs/rs/driver/rsdMesh.cpp b/libs/rs/driver/rsdMesh.cpp
index eb62ddb..50daf3e 100644
--- a/libs/rs/driver/rsdMesh.cpp
+++ b/libs/rs/driver/rsdMesh.cpp
@@ -35,7 +35,7 @@
}
drv = new RsdMeshObj(rsc, m);
m->mHal.drv = drv;
- return drv->init();
+ return drv->init(rsc);
}
void rsdMeshDraw(const Context *rsc, const Mesh *m, uint32_t primIndex, uint32_t start, uint32_t len) {
diff --git a/libs/rs/driver/rsdMeshObj.cpp b/libs/rs/driver/rsdMeshObj.cpp
index 99d79dc..893f046 100644
--- a/libs/rs/driver/rsdMeshObj.cpp
+++ b/libs/rs/driver/rsdMeshObj.cpp
@@ -50,14 +50,9 @@
}
bool RsdMeshObj::isValidGLComponent(const Element *elem, uint32_t fieldIdx) {
- // Do not create attribs for padding
- if (elem->getFieldName(fieldIdx)[0] == '#') {
- return false;
- }
-
// Only GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, GL_FLOAT are accepted.
// Filter rs types accordingly
- RsDataType dt = elem->getField(fieldIdx)->getComponent().getType();
+ RsDataType dt = elem->mHal.state.fields[fieldIdx]->mHal.state.dataType;
if (dt != RS_TYPE_FLOAT_32 && dt != RS_TYPE_UNSIGNED_8 &&
dt != RS_TYPE_UNSIGNED_16 && dt != RS_TYPE_SIGNED_8 &&
dt != RS_TYPE_SIGNED_16) {
@@ -65,7 +60,7 @@
}
// Now make sure they are not arrays
- uint32_t arraySize = elem->getFieldArraySize(fieldIdx);
+ uint32_t arraySize = elem->mHal.state.fieldArraySizes[fieldIdx];
if (arraySize != 1) {
return false;
}
@@ -73,15 +68,15 @@
return true;
}
-bool RsdMeshObj::init() {
+bool RsdMeshObj::init(const Context *rsc) {
- updateGLPrimitives();
+ updateGLPrimitives(rsc);
// Count the number of gl attrs to initialize
mAttribCount = 0;
for (uint32_t ct=0; ct < mRSMesh->mHal.state.vertexBuffersCount; ct++) {
const Element *elem = mRSMesh->mHal.state.vertexBuffers[ct]->getType()->getElement();
- for (uint32_t ct=0; ct < elem->getFieldCount(); ct++) {
+ for (uint32_t ct=0; ct < elem->mHal.state.fieldsCount; ct++) {
if (isValidGLComponent(elem, ct)) {
mAttribCount ++;
}
@@ -104,21 +99,21 @@
uint32_t userNum = 0;
for (uint32_t ct=0; ct < mRSMesh->mHal.state.vertexBuffersCount; ct++) {
const Element *elem = mRSMesh->mHal.state.vertexBuffers[ct]->getType()->getElement();
- uint32_t stride = elem->getSizeBytes();
- for (uint32_t fieldI=0; fieldI < elem->getFieldCount(); fieldI++) {
- const Component &c = elem->getField(fieldI)->getComponent();
+ uint32_t stride = elem->mHal.state.elementSizeBytes;
+ for (uint32_t fieldI=0; fieldI < elem->mHal.state.fieldsCount; fieldI++) {
+ const Element *f = elem->mHal.state.fields[fieldI];
if (!isValidGLComponent(elem, fieldI)) {
continue;
}
- mAttribs[userNum].size = c.getVectorSize();
- mAttribs[userNum].offset = elem->getFieldOffsetBytes(fieldI);
- mAttribs[userNum].type = rsdTypeToGLType(c.getType());
- mAttribs[userNum].normalized = c.getType() != RS_TYPE_FLOAT_32;//c.getIsNormalized();
+ mAttribs[userNum].size = f->mHal.state.vectorSize;
+ mAttribs[userNum].offset = elem->mHal.state.fieldOffsetBytes[fieldI];
+ mAttribs[userNum].type = rsdTypeToGLType(f->mHal.state.dataType);
+ mAttribs[userNum].normalized = f->mHal.state.dataType != RS_TYPE_FLOAT_32;
mAttribs[userNum].stride = stride;
String8 tmp(RS_SHADER_ATTR);
- tmp.append(elem->getFieldName(fieldI));
+ tmp.append(elem->mHal.state.fieldNames[fieldI]);
mAttribs[userNum].name.setTo(tmp.string());
// Remember which allocation this attribute came from
@@ -133,7 +128,7 @@
void RsdMeshObj::renderPrimitiveRange(const Context *rsc, uint32_t primIndex,
uint32_t start, uint32_t len) const {
if (len < 1 || primIndex >= mRSMesh->mHal.state.primitivesCount || mAttribCount == 0) {
- ALOGE("Invalid mesh or parameters");
+ rsc->setError(RS_ERROR_FATAL_DRIVER, "Invalid mesh or parameters");
return;
}
@@ -186,7 +181,7 @@
rsdGLCheckError(rsc, "Mesh::renderPrimitiveRange");
}
-void RsdMeshObj::updateGLPrimitives() {
+void RsdMeshObj::updateGLPrimitives(const Context *rsc) {
mGLPrimitives = new uint32_t[mRSMesh->mHal.state.primitivesCount];
for (uint32_t i = 0; i < mRSMesh->mHal.state.primitivesCount; i ++) {
switch (mRSMesh->mHal.state.primitives[i]) {
@@ -196,6 +191,7 @@
case RS_PRIMITIVE_TRIANGLE: mGLPrimitives[i] = GL_TRIANGLES; break;
case RS_PRIMITIVE_TRIANGLE_STRIP: mGLPrimitives[i] = GL_TRIANGLE_STRIP; break;
case RS_PRIMITIVE_TRIANGLE_FAN: mGLPrimitives[i] = GL_TRIANGLE_FAN; break;
+ default: rsc->setError(RS_ERROR_FATAL_DRIVER, "Invalid mesh primitive"); break;
}
}
}
diff --git a/libs/rs/driver/rsdMeshObj.h b/libs/rs/driver/rsdMeshObj.h
index 8b1271b..1370f01 100644
--- a/libs/rs/driver/rsdMeshObj.h
+++ b/libs/rs/driver/rsdMeshObj.h
@@ -37,15 +37,16 @@
const android::renderscript::Mesh *);
~RsdMeshObj();
- void renderPrimitiveRange(const android::renderscript::Context *, uint32_t primIndex, uint32_t start, uint32_t len) const;
+ void renderPrimitiveRange(const android::renderscript::Context *,
+ uint32_t primIndex, uint32_t start, uint32_t len) const;
- bool init();
+ bool init(const android::renderscript::Context *rsc);
protected:
const android::renderscript::Mesh *mRSMesh;
uint32_t *mGLPrimitives;
- void updateGLPrimitives();
+ void updateGLPrimitives(const android::renderscript::Context *rsc);
bool isValidGLComponent(const android::renderscript::Element *elem, uint32_t fieldIdx);
// Attribues that allow us to map to GL
diff --git a/libs/rs/driver/rsdPath.cpp b/libs/rs/driver/rsdPath.cpp
new file mode 100644
index 0000000..e04bc02
--- /dev/null
+++ b/libs/rs/driver/rsdPath.cpp
@@ -0,0 +1,185 @@
+/*
+ * 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.
+ */
+
+#include <GLES/gl.h>
+#include <GLES2/gl2.h>
+#include <GLES/glext.h>
+
+#include <rs_hal.h>
+#include <rsContext.h>
+#include <rsPath.h>
+
+#include "rsdCore.h"
+#include "rsdPath.h"
+#include "rsdAllocation.h"
+#include "rsdGL.h"
+#include "rsdVertexArray.h"
+#include "rsdShaderCache.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+class DrvPath {
+protected:
+ DrvPath();
+public:
+ virtual ~DrvPath();
+ virtual void draw(Context *) = 0;
+};
+
+class DrvPathStatic : public DrvPath {
+public:
+ typedef struct {
+ float x1, xc, x2;
+ float y1, yc, y2;
+ } segment_t;
+
+ segment_t *mSegments;
+ uint32_t mSegmentCount;
+
+ DrvPathStatic(const Allocation *vtx, const Allocation *loops);
+ virtual ~DrvPathStatic();
+
+ virtual void draw(Context *);
+};
+
+class DrvPathDynamic : public DrvPath {
+public:
+ DrvPathDynamic();
+ virtual ~DrvPathDynamic();
+};
+
+static void cleanup(const Context *rsc, const Path *m) {
+ DrvPath *dp = (DrvPath *)m->mHal.drv;
+ if (dp) {
+ delete dp;
+ }
+}
+
+bool rsdPathInitStatic(const Context *rsc, const Path *m,
+ const Allocation *vtx, const Allocation *loops) {
+ DrvPathStatic *drv = NULL;
+ cleanup(rsc, m);
+
+ DrvPathStatic *dps = new DrvPathStatic(vtx, loops);
+ //LOGE("init path m %p, %p", m, dps);
+ m->mHal.drv = dps;
+ return dps != NULL;
+}
+
+bool rsdPathInitDynamic(const Context *rsc, const Path *m) {
+ return false;
+}
+
+
+void rsdPathDraw(const Context *rsc, const Path *m) {
+ //LOGE("render m=%p", m);
+
+ DrvPath *drv = (DrvPath *)m->mHal.drv;
+ if(drv) {
+ //LOGE("render 2 drv=%p", drv);
+ drv->draw((Context *)rsc);
+ }
+}
+
+void rsdPathDestroy(const Context *rsc, const Path *m) {
+ cleanup(rsc, m);
+ m->mHal.drv = NULL;
+}
+
+
+
+
+DrvPath::DrvPath() {
+}
+
+DrvPath::~DrvPath() {
+}
+
+DrvPathStatic::DrvPathStatic(const Allocation *vtx, const Allocation *loops) {
+ mSegmentCount = vtx->getType()->getDimX() / 3;
+ mSegments = new segment_t[mSegmentCount];
+
+ const float *fin = (const float *)vtx->getPtr();
+ for (uint32_t ct=0; ct < mSegmentCount; ct++) {
+ segment_t *s = &mSegments[ct];
+ s->x1 = fin[0];
+ s->y1 = fin[1];
+
+ s->xc = fin[2];
+ s->yc = fin[3];
+
+ s->x2 = fin[4];
+ s->y2 = fin[5];
+ fin += 6;
+ }
+}
+
+DrvPathStatic::~DrvPathStatic() {
+}
+
+void DrvPathStatic::draw(Context *rsc) {
+ const static float color[24] = {
+ 1.f, 0.f, 0.f, 1.f, 0.5f, 0.f, 0.f, 1.f,
+ 1.f, 0.f, 0.f, 1.f, 0.5f, 0.f, 0.f, 1.f,
+ 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f};
+ float vtx[12];
+
+ //LOGE("draw");
+ if (!rsc->setupCheck()) {
+ return;
+ }
+
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+ if (!dc->gl.shaderCache->setup(rsc)) {
+ return;
+ }
+
+ RsdVertexArray::Attrib attribs[2];
+ attribs[0].set(GL_FLOAT, 2, 8, false, (uint32_t)vtx, "ATTRIB_position");
+ attribs[1].set(GL_FLOAT, 4, 16, false, (uint32_t)color, "ATTRIB_color");
+ RsdVertexArray va(attribs, 2);
+ va.setup(rsc);
+
+ //LOGE("mSegmentCount %i", mSegmentCount);
+ for (uint32_t ct=0; ct < mSegmentCount; ct++) {
+ segment_t *s = &mSegments[ct];
+
+ vtx[0] = s->x1;
+ vtx[1] = s->y1;
+ vtx[2] = s->xc;
+ vtx[3] = s->yc;
+
+ vtx[4] = s->x2;
+ vtx[5] = s->y2;
+ vtx[6] = s->xc;
+ vtx[7] = s->yc;
+
+ vtx[8] = s->x1;
+ vtx[9] = s->y1;
+ vtx[10] = s->x2;
+ vtx[11] = s->y2;
+
+ RSD_CALL_GL(glDrawArrays, GL_LINES, 0, 6);
+ }
+
+}
+
+DrvPathDynamic::DrvPathDynamic() {
+}
+
+DrvPathDynamic::~DrvPathDynamic() {
+}
diff --git a/libs/rs/driver/rsdPath.h b/libs/rs/driver/rsdPath.h
new file mode 100644
index 0000000..fa00972
--- /dev/null
+++ b/libs/rs/driver/rsdPath.h
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+#ifndef RSD_PATH_H
+#define RSD_PATH_H
+
+#include <rs_hal.h>
+
+
+bool rsdPathInitStatic(const android::renderscript::Context *rsc,
+ const android::renderscript::Path *m,
+ const android::renderscript::Allocation *vertex,
+ const android::renderscript::Allocation *loops);
+bool rsdPathInitDynamic(const android::renderscript::Context *rsc,
+ const android::renderscript::Path *m);
+void rsdPathDraw(const android::renderscript::Context *rsc,
+ const android::renderscript::Path *m);
+void rsdPathDestroy(const android::renderscript::Context *rsc,
+ const android::renderscript::Path *m);
+
+
+#endif
diff --git a/libs/rs/driver/rsdProgramRaster.cpp b/libs/rs/driver/rsdProgramRaster.cpp
index b493759..e5a0291 100644
--- a/libs/rs/driver/rsdProgramRaster.cpp
+++ b/libs/rs/driver/rsdProgramRaster.cpp
@@ -45,6 +45,9 @@
case RS_CULL_NONE:
RSD_CALL_GL(glDisable, GL_CULL_FACE);
break;
+ default:
+ rsc->setError(RS_ERROR_FATAL_DRIVER, "Invalid cull type");
+ break;
}
}
diff --git a/libs/rs/driver/rsdProgramStore.cpp b/libs/rs/driver/rsdProgramStore.cpp
index fca9ba9..c1295e8 100644
--- a/libs/rs/driver/rsdProgramStore.cpp
+++ b/libs/rs/driver/rsdProgramStore.cpp
@@ -111,7 +111,7 @@
drv->blendSrc = GL_SRC_ALPHA_SATURATE;
break;
default:
- ALOGE("Unknown blend src mode.");
+ rsc->setError(RS_ERROR_FATAL_DRIVER, "Unknown blend src mode.");
goto error;
}
@@ -141,7 +141,7 @@
drv->blendDst = GL_ONE_MINUS_DST_ALPHA;
break;
default:
- ALOGE("Unknown blend dst mode.");
+ rsc->setError(RS_ERROR_FATAL_DRIVER, "Unknown blend dst mode.");
goto error;
}
diff --git a/libs/rs/driver/rsdRuntimeStubs.cpp b/libs/rs/driver/rsdRuntimeStubs.cpp
index 14c2970..44bfb1c 100644
--- a/libs/rs/driver/rsdRuntimeStubs.cpp
+++ b/libs/rs/driver/rsdRuntimeStubs.cpp
@@ -25,6 +25,7 @@
#include "rsdCore.h"
#include "rsdRuntime.h"
+#include "rsdPath.h"
#include <time.h>
@@ -89,6 +90,16 @@
rsrBindTexture(rsc, sc, pf, slot, a);
}
+static void SC_BindVertexConstant(ProgramVertex *pv, uint32_t slot, Allocation *a) {
+ GET_TLS();
+ rsrBindConstant(rsc, sc, pv, slot, a);
+}
+
+static void SC_BindFragmentConstant(ProgramFragment *pf, uint32_t slot, Allocation *a) {
+ GET_TLS();
+ rsrBindConstant(rsc, sc, pf, slot, a);
+}
+
static void SC_BindSampler(ProgramFragment *pf, uint32_t slot, Sampler *s) {
GET_TLS();
rsrBindSampler(rsc, sc, pf, slot, s);
@@ -204,6 +215,12 @@
rsrDrawRect(rsc, sc, x1, y1, x2, y2, z);
}
+static void SC_DrawPath(Path *p) {
+ GET_TLS();
+ //rsrDrawPath(rsc, sc, p);
+ rsdPathDraw(rsc, p);
+}
+
static void SC_DrawMesh(Mesh *m) {
GET_TLS();
rsrDrawMesh(rsc, sc, m);
@@ -533,6 +550,10 @@
{ "_Z13rsClearObjectP9rs_script", (void *)&SC_ClearObject, true },
{ "_Z10rsIsObject9rs_script", (void *)&SC_IsObject, true },
+ { "_Z11rsSetObjectP7rs_pathS_", (void *)&SC_SetObject, true },
+ { "_Z13rsClearObjectP7rs_path", (void *)&SC_ClearObject, true },
+ { "_Z10rsIsObject7rs_path", (void *)&SC_IsObject, true },
+
{ "_Z11rsSetObjectP7rs_meshS_", (void *)&SC_SetObject, true },
{ "_Z13rsClearObjectP7rs_mesh", (void *)&SC_ClearObject, true },
{ "_Z10rsIsObject7rs_mesh", (void *)&SC_IsObject, true },
@@ -580,6 +601,8 @@
{ "_Z20rsgBindProgramRaster17rs_program_raster", (void *)&SC_BindProgramRaster, false },
{ "_Z14rsgBindSampler19rs_program_fragmentj10rs_sampler", (void *)&SC_BindSampler, false },
{ "_Z14rsgBindTexture19rs_program_fragmentj13rs_allocation", (void *)&SC_BindTexture, false },
+ { "_Z15rsgBindConstant19rs_program_fragmentj13rs_allocation", (void *)&SC_BindFragmentConstant, false },
+ { "_Z15rsgBindConstant17rs_program_vertexj13rs_allocation", (void *)&SC_BindVertexConstant, false },
{ "_Z36rsgProgramVertexLoadProjectionMatrixPK12rs_matrix4x4", (void *)&SC_VpLoadProjectionMatrix, false },
{ "_Z31rsgProgramVertexLoadModelMatrixPK12rs_matrix4x4", (void *)&SC_VpLoadModelMatrix, false },
@@ -603,6 +626,8 @@
{ "_Z11rsgDrawMesh7rs_meshjjj", (void *)&SC_DrawMeshPrimitiveRange, false },
{ "_Z25rsgMeshComputeBoundingBox7rs_meshPfS0_S0_S0_S0_S0_", (void *)&SC_MeshComputeBoundingBox, false },
+ { "_Z11rsgDrawPath7rs_path", (void *)&SC_DrawPath, false },
+
{ "_Z13rsgClearColorffff", (void *)&SC_ClearColor, false },
{ "_Z13rsgClearDepthf", (void *)&SC_ClearDepth, false },
diff --git a/libs/rs/driver/rsdShader.cpp b/libs/rs/driver/rsdShader.cpp
index 056a33a..3bca794 100644
--- a/libs/rs/driver/rsdShader.cpp
+++ b/libs/rs/driver/rsdShader.cpp
@@ -90,12 +90,12 @@
String8 s;
for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
const Element *e = mRSProgram->mHal.state.inputElements[ct];
- for (uint32_t field=0; field < e->getFieldCount(); field++) {
- const Element *f = e->getField(field);
+ for (uint32_t field=0; field < e->mHal.state.fieldsCount; field++) {
+ const Element *f = e->mHal.state.fields[field];
// Cannot be complex
- rsAssert(!f->getFieldCount());
- switch (f->getComponent().getVectorSize()) {
+ rsAssert(!f->mHal.state.fieldsCount);
+ switch (f->mHal.state.vectorSize) {
case 1: s.append("attribute float ATTRIB_"); break;
case 2: s.append("attribute vec2 ATTRIB_"); break;
case 3: s.append("attribute vec3 ATTRIB_"); break;
@@ -104,7 +104,7 @@
rsAssert(0);
}
- s.append(e->getFieldName(field));
+ s.append(e->mHal.state.fieldNames[field]);
s.append(";\n");
}
}
@@ -114,17 +114,13 @@
void RsdShader::appendAttributes() {
for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
const Element *e = mRSProgram->mHal.state.inputElements[ct];
- for (uint32_t field=0; field < e->getFieldCount(); field++) {
- const Element *f = e->getField(field);
- const char *fn = e->getFieldName(field);
-
- if (fn[0] == '#') {
- continue;
- }
+ for (uint32_t field=0; field < e->mHal.state.fieldsCount; field++) {
+ const Element *f = e->mHal.state.fields[field];
+ const char *fn = e->mHal.state.fieldNames[field];
// Cannot be complex
- rsAssert(!f->getFieldCount());
- switch (f->getComponent().getVectorSize()) {
+ rsAssert(!f->mHal.state.fieldsCount);
+ switch (f->mHal.state.vectorSize) {
case 1: mShader.append("attribute float ATTRIB_"); break;
case 2: mShader.append("attribute vec2 ATTRIB_"); break;
case 3: mShader.append("attribute vec3 ATTRIB_"); break;
@@ -215,24 +211,20 @@
void RsdShader::appendUserConstants() {
for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
const Element *e = mRSProgram->mHal.state.constantTypes[ct]->getElement();
- for (uint32_t field=0; field < e->getFieldCount(); field++) {
- const Element *f = e->getField(field);
- const char *fn = e->getFieldName(field);
-
- if (fn[0] == '#') {
- continue;
- }
+ for (uint32_t field=0; field < e->mHal.state.fieldsCount; field++) {
+ const Element *f = e->mHal.state.fields[field];
+ const char *fn = e->mHal.state.fieldNames[field];
// Cannot be complex
- rsAssert(!f->getFieldCount());
- if (f->getType() == RS_TYPE_MATRIX_4X4) {
+ rsAssert(!f->mHal.state.fieldsCount);
+ if (f->mHal.state.dataType == RS_TYPE_MATRIX_4X4) {
mShader.append("uniform mat4 UNI_");
- } else if (f->getType() == RS_TYPE_MATRIX_3X3) {
+ } else if (f->mHal.state.dataType == RS_TYPE_MATRIX_3X3) {
mShader.append("uniform mat3 UNI_");
- } else if (f->getType() == RS_TYPE_MATRIX_2X2) {
+ } else if (f->mHal.state.dataType == RS_TYPE_MATRIX_2X2) {
mShader.append("uniform mat2 UNI_");
} else {
- switch (f->getComponent().getVectorSize()) {
+ switch (f->mHal.state.vectorSize) {
case 1: mShader.append("uniform float UNI_"); break;
case 2: mShader.append("uniform vec2 UNI_"); break;
case 3: mShader.append("uniform vec3 UNI_"); break;
@@ -243,8 +235,8 @@
}
mShader.append(fn);
- if (e->getFieldArraySize(field) > 1) {
- mShader.appendFormat("[%d]", e->getFieldArraySize(field));
+ if (e->mHal.state.fieldArraySizes[field] > 1) {
+ mShader.appendFormat("[%d]", e->mHal.state.fieldArraySizes[field]);
}
mShader.append(";\n");
}
@@ -252,8 +244,8 @@
}
void RsdShader::logUniform(const Element *field, const float *fd, uint32_t arraySize ) {
- RsDataType dataType = field->getType();
- uint32_t elementSize = field->getSizeBytes() / sizeof(float);
+ RsDataType dataType = field->mHal.state.dataType;
+ uint32_t elementSize = field->mHal.state.elementSizeBytes / sizeof(float);
for (uint32_t i = 0; i < arraySize; i ++) {
if (arraySize > 1) {
ALOGV("Array Element [%u]", i);
@@ -274,7 +266,7 @@
ALOGV("{%f, %f", fd[0], fd[2]);
ALOGV(" %f, %f}", fd[1], fd[3]);
} else {
- switch (field->getComponent().getVectorSize()) {
+ switch (field->mHal.state.vectorSize) {
case 1:
ALOGV("Uniform 1 = %f", fd[0]);
break;
@@ -299,7 +291,7 @@
void RsdShader::setUniform(const Context *rsc, const Element *field, const float *fd,
int32_t slot, uint32_t arraySize ) {
- RsDataType dataType = field->getType();
+ RsDataType dataType = field->mHal.state.dataType;
if (dataType == RS_TYPE_MATRIX_4X4) {
RSD_CALL_GL(glUniformMatrix4fv, slot, arraySize, GL_FALSE, fd);
} else if (dataType == RS_TYPE_MATRIX_3X3) {
@@ -307,7 +299,7 @@
} else if (dataType == RS_TYPE_MATRIX_2X2) {
RSD_CALL_GL(glUniformMatrix2fv, slot, arraySize, GL_FALSE, fd);
} else {
- switch (field->getComponent().getVectorSize()) {
+ switch (field->mHal.state.vectorSize) {
case 1:
RSD_CALL_GL(glUniform1fv, slot, arraySize, fd);
break;
@@ -462,15 +454,11 @@
const uint8_t *data = static_cast<const uint8_t *>(alloc->getPtr());
const Element *e = mRSProgram->mHal.state.constantTypes[ct]->getElement();
- for (uint32_t field=0; field < e->getFieldCount(); field++) {
- const Element *f = e->getField(field);
- const char *fieldName = e->getFieldName(field);
- // If this field is padding, skip it
- if (fieldName[0] == '#') {
- continue;
- }
+ for (uint32_t field=0; field < e->mHal.state.fieldsCount; field++) {
+ const Element *f = e->mHal.state.fields[field];
+ const char *fieldName = e->mHal.state.fieldNames[field];
- uint32_t offset = e->getFieldOffsetBytes(field);
+ uint32_t offset = e->mHal.state.fieldOffsetBytes[field];
const float *fd = reinterpret_cast<const float *>(&data[offset]);
int32_t slot = -1;
@@ -509,22 +497,13 @@
mAttribCount = 0;
for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
const Element *elem = mRSProgram->mHal.state.inputElements[ct];
- for (uint32_t field=0; field < elem->getFieldCount(); field++) {
- if (elem->getFieldName(field)[0] != '#') {
- mAttribCount ++;
- }
- }
+ mAttribCount += elem->mHal.state.fieldsCount;
}
mUniformCount = 0;
for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
const Element *elem = mRSProgram->mHal.state.constantTypes[ct]->getElement();
-
- for (uint32_t field=0; field < elem->getFieldCount(); field++) {
- if (elem->getFieldName(field)[0] != '#') {
- mUniformCount ++;
- }
- }
+ mUniformCount += elem->mHal.state.fieldsCount;
}
mUniformCount += mRSProgram->mHal.state.texturesCount;
@@ -544,17 +523,17 @@
void RsdShader::initAddUserElement(const Element *e, String8 *names, uint32_t *arrayLengths,
uint32_t *count, const char *prefix) {
- rsAssert(e->getFieldCount());
- for (uint32_t ct=0; ct < e->getFieldCount(); ct++) {
- const Element *ce = e->getField(ct);
- if (ce->getFieldCount()) {
+ rsAssert(e->mHal.state.fieldsCount);
+ for (uint32_t ct=0; ct < e->mHal.state.fieldsCount; ct++) {
+ const Element *ce = e->mHal.state.fields[ct];
+ if (ce->mHal.state.fieldsCount) {
initAddUserElement(ce, names, arrayLengths, count, prefix);
- } else if (e->getFieldName(ct)[0] != '#') {
+ } else {
String8 tmp(prefix);
- tmp.append(e->getFieldName(ct));
+ tmp.append(e->mHal.state.fieldNames[ct]);
names[*count].setTo(tmp.string());
if (arrayLengths) {
- arrayLengths[*count] = e->getFieldArraySize(ct);
+ arrayLengths[*count] = e->mHal.state.fieldArraySizes[ct];
}
(*count)++;
}
diff --git a/libs/rs/driver/rsdShaderCache.h b/libs/rs/driver/rsdShaderCache.h
index d64780b..0beecae 100644
--- a/libs/rs/driver/rsdShaderCache.h
+++ b/libs/rs/driver/rsdShaderCache.h
@@ -98,7 +98,8 @@
struct ProgramEntry {
ProgramEntry(uint32_t numVtxAttr, uint32_t numVtxUnis,
uint32_t numFragUnis) : vtx(0), frag(0), program(0), vtxAttrCount(0),
- vtxAttrs(0), vtxUniforms(0), fragUniforms(0) {
+ vtxAttrs(0), vtxUniforms(0), fragUniforms(0),
+ fragUniformIsSTO(0) {
vtxAttrCount = numVtxAttr;
if (numVtxAttr) {
vtxAttrs = new AttrData[numVtxAttr];
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 09a2986..6759bc7 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -42,6 +42,7 @@
param RsType vtype
param RsAllocationMipmapControl mips
param uint32_t usages
+ param uint32_t ptr
ret RsAllocation
}
@@ -392,3 +393,13 @@
param uint32_t *primType
ret RsMesh
}
+
+PathCreate {
+ param RsPathPrimitive pp
+ param bool isStatic
+ param RsAllocation vertex
+ param RsAllocation loops
+ param float quality
+ ret RsPath
+ }
+
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index 5f45abf..02c6809 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -22,21 +22,22 @@
using namespace android::renderscript;
Allocation::Allocation(Context *rsc, const Type *type, uint32_t usages,
- RsAllocationMipmapControl mc)
+ RsAllocationMipmapControl mc, void * ptr)
: ObjectBase(rsc) {
memset(&mHal, 0, sizeof(mHal));
mHal.state.mipmapControl = RS_ALLOCATION_MIPMAP_NONE;
mHal.state.usageFlags = usages;
mHal.state.mipmapControl = mc;
+ mHal.state.usrPtr = ptr;
setType(type);
updateCache();
}
Allocation * Allocation::createAllocation(Context *rsc, const Type *type, uint32_t usages,
- RsAllocationMipmapControl mc) {
- Allocation *a = new Allocation(rsc, type, usages, mc);
+ RsAllocationMipmapControl mc, void * ptr) {
+ Allocation *a = new Allocation(rsc, type, usages, mc, ptr);
if (!rsc->mHal.funcs.allocation.init(rsc, a, type->getElement()->getHasReferences())) {
rsc->setError(RS_ERROR_FATAL_DRIVER, "Allocation::Allocation, alloc failure");
@@ -577,8 +578,8 @@
RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype,
RsAllocationMipmapControl mips,
- uint32_t usages) {
- Allocation * alloc = Allocation::createAllocation(rsc, static_cast<Type *>(vtype), usages, mips);
+ uint32_t usages, uint32_t ptr) {
+ Allocation * alloc = Allocation::createAllocation(rsc, static_cast<Type *>(vtype), usages, mips, (void *)ptr);
if (!alloc) {
return NULL;
}
@@ -591,7 +592,7 @@
const void *data, size_t data_length, uint32_t usages) {
Type *t = static_cast<Type *>(vtype);
- RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mips, usages);
+ RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mips, usages, 0);
Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
if (texAlloc == NULL) {
ALOGE("Memory allocation failure");
@@ -615,7 +616,7 @@
// Cubemap allocation's faces should be Width by Width each.
// Source data should have 6 * Width by Width pixels
// Error checking is done in the java layer
- RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mips, usages);
+ RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mips, usages, 0);
Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
if (texAlloc == NULL) {
ALOGE("Memory allocation failure");
diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h
index a26d835..58a582b 100644
--- a/libs/rs/rsAllocation.h
+++ b/libs/rs/rsAllocation.h
@@ -68,7 +68,8 @@
Hal mHal;
static Allocation * createAllocation(Context *rsc, const Type *, uint32_t usages,
- RsAllocationMipmapControl mc = RS_ALLOCATION_MIPMAP_NONE);
+ RsAllocationMipmapControl mc = RS_ALLOCATION_MIPMAP_NONE,
+ void *ptr = 0);
virtual ~Allocation();
void updateCache();
@@ -137,7 +138,7 @@
private:
void freeChildrenUnlocked();
- Allocation(Context *rsc, const Type *, uint32_t usages, RsAllocationMipmapControl mc);
+ Allocation(Context *rsc, const Type *, uint32_t usages, RsAllocationMipmapControl mc, void *ptr);
uint32_t getPackedSize() const;
static void writePackedData(const Type *type, uint8_t *dst, const uint8_t *src, bool dstPadded);
diff --git a/libs/rs/rsComponent.cpp b/libs/rs/rsComponent.cpp
index 21b98f6..9c2c200 100644
--- a/libs/rs/rsComponent.cpp
+++ b/libs/rs/rsComponent.cpp
@@ -62,6 +62,7 @@
rsAssert(mNormalized == true);
break;
default:
+ rsAssert(mKind != RS_KIND_INVALID);
break;
}
@@ -167,6 +168,9 @@
case RS_TYPE_BOOLEAN:
mTypeBits = 8;
break;
+ default:
+ rsAssert(mType != RS_TYPE_INVALID);
+ break;
}
mBitsUnpadded = mTypeBits * mVectorSize;
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 1a34bd5..adaefc6 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -361,6 +361,7 @@
#else
setpriority(PRIO_PROCESS, mNativeThreadId, p);
#endif
+ mHal.funcs.setPriority(this, mThreadPriority);
}
Context::Context() {
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index a844a20..05c799e 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -32,6 +32,7 @@
#include "rsAdapter.h"
#include "rsSampler.h"
#include "rsFont.h"
+#include "rsPath.h"
#include "rsProgramFragment.h"
#include "rsProgramStore.h"
#include "rsProgramRaster.h"
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
index dff9585..fb2892c 100644
--- a/libs/rs/rsElement.cpp
+++ b/libs/rs/rsElement.cpp
@@ -27,6 +27,7 @@
mFields = NULL;
mFieldCount = 0;
mHasReference = false;
+ memset(&mHal, 0, sizeof(mHal));
}
Element::~Element() {
@@ -47,6 +48,12 @@
mFields = NULL;
mFieldCount = 0;
mHasReference = false;
+
+ delete [] mHal.state.fields;
+ delete [] mHal.state.fieldArraySizes;
+ delete [] mHal.state.fieldNames;
+ delete [] mHal.state.fieldNameLengths;
+ delete [] mHal.state.fieldOffsetBytes;
}
size_t Element::getSizeBits() const {
@@ -157,16 +164,36 @@
}
void Element::compute() {
+ mHal.state.dataType = mComponent.getType();
+ mHal.state.dataKind = mComponent.getKind();
+ mHal.state.vectorSize = mComponent.getVectorSize();
+
if (mFieldCount == 0) {
mBits = mComponent.getBits();
mBitsUnpadded = mComponent.getBitsUnpadded();
mHasReference = mComponent.isReference();
+
+ mHal.state.elementSizeBytes = getSizeBytes();
return;
}
+ uint32_t noPaddingFieldCount = 0;
+ for (uint32_t ct = 0; ct < mFieldCount; ct ++) {
+ if (mFields[ct].name.string()[0] != '#') {
+ noPaddingFieldCount ++;
+ }
+ }
+
+ mHal.state.fields = new const Element*[noPaddingFieldCount];
+ mHal.state.fieldArraySizes = new uint32_t[noPaddingFieldCount];
+ mHal.state.fieldNames = new const char*[noPaddingFieldCount];
+ mHal.state.fieldNameLengths = new uint32_t[noPaddingFieldCount];
+ mHal.state.fieldOffsetBytes = new uint32_t[noPaddingFieldCount];
+ mHal.state.fieldsCount = noPaddingFieldCount;
+
size_t bits = 0;
size_t bitsUnpadded = 0;
- for (size_t ct=0; ct < mFieldCount; ct++) {
+ for (size_t ct = 0, ctNoPadding = 0; ct < mFieldCount; ct++) {
mFields[ct].offsetBits = bits;
mFields[ct].offsetBitsUnpadded = bitsUnpadded;
bits += mFields[ct].e->getSizeBits() * mFields[ct].arraySize;
@@ -175,8 +202,21 @@
if (mFields[ct].e->mHasReference) {
mHasReference = true;
}
+
+ if (mFields[ct].name.string()[0] == '#') {
+ continue;
+ }
+
+ mHal.state.fields[ctNoPadding] = mFields[ct].e.get();
+ mHal.state.fieldArraySizes[ctNoPadding] = mFields[ct].arraySize;
+ mHal.state.fieldNames[ctNoPadding] = mFields[ct].name.string();
+ mHal.state.fieldNameLengths[ctNoPadding] = mFields[ct].name.length() + 1; // to include 0
+ mHal.state.fieldOffsetBytes[ctNoPadding] = mFields[ct].offsetBits >> 3;
+
+ ctNoPadding ++;
}
+ mHal.state.elementSizeBytes = getSizeBytes();
}
ObjectBaseRef<const Element> Element::createRef(Context *rsc, RsDataType dt, RsDataKind dk,
diff --git a/libs/rs/rsElement.h b/libs/rs/rsElement.h
index 04010fa..4b6b460 100644
--- a/libs/rs/rsElement.h
+++ b/libs/rs/rsElement.h
@@ -24,10 +24,38 @@
// ---------------------------------------------------------------------------
namespace android {
namespace renderscript {
-
+/*****************************************************************************
+ * CAUTION
+ *
+ * Any layout changes for this class may require a corresponding change to be
+ * made to frameworks/compile/libbcc/lib/ScriptCRT/rs_core.c, which contains
+ * a partial copy of the information below.
+ *
+ *****************************************************************************/
// An element is a group of Components that occupies one cell in a structure.
class Element : public ObjectBase {
public:
+ struct Hal {
+ mutable void *drv;
+
+ struct State {
+ RsDataType dataType;
+ RsDataKind dataKind;
+ uint32_t vectorSize;
+ uint32_t elementSizeBytes;
+
+ // Subelements
+ const Element **fields;
+ uint32_t *fieldArraySizes;
+ const char **fieldNames;
+ uint32_t *fieldNameLengths;
+ uint32_t *fieldOffsetBytes;
+ uint32_t fieldsCount;
+ };
+ State state;
+ };
+ Hal mHal;
+
class Builder {
public:
Builder();
diff --git a/libs/rs/rsMesh.h b/libs/rs/rsMesh.h
index 0fc73fb..166b5d3 100644
--- a/libs/rs/rsMesh.h
+++ b/libs/rs/rsMesh.h
@@ -23,20 +23,18 @@
// ---------------------------------------------------------------------------
namespace android {
namespace renderscript {
-
+/*****************************************************************************
+ * CAUTION
+ *
+ * Any layout changes for this class may require a corresponding change to be
+ * made to frameworks/compile/libbcc/lib/ScriptCRT/rs_core.c, which contains
+ * a partial copy of the information below.
+ *
+ *****************************************************************************/
// An element is a group of Components that occupies one cell in a structure.
class Mesh : public ObjectBase {
public:
- Mesh(Context *);
- Mesh(Context *, uint32_t vertexBuffersCount, uint32_t primitivesCount);
- ~Mesh();
-
- virtual void serialize(OStream *stream) const;
- virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_MESH; }
- static Mesh *createFromStream(Context *rsc, IStream *stream);
- void init();
-
struct Hal {
mutable void *drv;
@@ -57,6 +55,15 @@
};
Hal mHal;
+ Mesh(Context *);
+ Mesh(Context *, uint32_t vertexBuffersCount, uint32_t primitivesCount);
+ ~Mesh();
+
+ virtual void serialize(OStream *stream) const;
+ virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_MESH; }
+ static Mesh *createFromStream(Context *rsc, IStream *stream);
+ void init();
+
void setVertexBuffer(Allocation *vb, uint32_t index) {
mVertexBuffers[index].set(vb);
mHal.state.vertexBuffers[index] = vb;
diff --git a/libs/rs/rsPath.cpp b/libs/rs/rsPath.cpp
new file mode 100644
index 0000000..c4f4978
--- /dev/null
+++ b/libs/rs/rsPath.cpp
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#include "rsContext.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+
+Path::Path(Context *rsc) : ObjectBase(rsc) {
+}
+
+Path::Path(Context *rsc, RsPathPrimitive pp, bool isStatic,
+ Allocation *vtx, Allocation *loops, float quality)
+: ObjectBase(rsc) {
+
+ memset(&mHal, 0, sizeof(mHal));
+ mHal.state.quality = quality;
+ mHal.state.primitive = pp;
+
+ //LOGE("i1");
+ rsc->mHal.funcs.path.initStatic(rsc, this, vtx, loops);
+
+ //LOGE("i2");
+}
+
+Path::Path(Context *rsc, uint32_t vertexBuffersCount, uint32_t primitivesCount)
+: ObjectBase(rsc) {
+
+}
+
+Path::~Path() {
+
+}
+
+
+void Path::rasterize(const BezierSegment_t *s, uint32_t num, Allocation *alloc) {
+
+ for (uint32_t i=0; i < num; i++) {
+
+ }
+
+}
+
+void Path::render(Context *rsc) {
+}
+
+void Path::serialize(OStream *stream) const {
+
+}
+
+RsA3DClassID Path::getClassId() const {
+ return RS_A3D_CLASS_ID_UNKNOWN;
+}
+
+namespace android {
+namespace renderscript {
+
+RsPath rsi_PathCreate(Context *rsc, RsPathPrimitive pp, bool isStatic,
+ RsAllocation vtx, RsAllocation loops, float quality) {
+ return new Path(rsc, pp, isStatic, (Allocation *)vtx, (Allocation *)loops, quality);
+}
+
+}
+}
diff --git a/libs/rs/rsPath.h b/libs/rs/rsPath.h
new file mode 100644
index 0000000..dac795e
--- /dev/null
+++ b/libs/rs/rsPath.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_RS_PATH_H
+#define ANDROID_RS_PATH_H
+
+
+#include "RenderScript.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+class Path : public ObjectBase {
+public:
+ struct {
+ mutable void * drv;
+
+ struct State {
+ RsPathPrimitive primitive;
+ float quality;
+ };
+ State state;
+ } mHal;
+
+ Path(Context *);
+ Path(Context *, uint32_t vertexBuffersCount, uint32_t primitivesCount);
+ Path(Context *, RsPathPrimitive pp, bool isStatic, Allocation *vtx, Allocation *loop, float q);
+
+ ~Path();
+
+ void render(Context *);
+ virtual void serialize(OStream *stream) const;
+ virtual RsA3DClassID getClassId() const;
+
+private:
+
+
+ typedef struct {
+ float x[4];
+ float y[4];
+ } BezierSegment_t;
+
+ bool subdivideCheck(const BezierSegment_t *s, float u1, float u2);
+
+ void rasterize(const BezierSegment_t *s, uint32_t num, Allocation *alloc);
+
+
+};
+
+}
+}
+#endif //ANDROID_RS_PATH_H
+
+
+
diff --git a/libs/rs/rsRuntime.h b/libs/rs/rsRuntime.h
index cb962a8..3bded62 100644
--- a/libs/rs/rsRuntime.h
+++ b/libs/rs/rsRuntime.h
@@ -30,6 +30,8 @@
//////////////////////////////////////////////////////////////////////////////
void rsrBindTexture(Context *, Script *, ProgramFragment *, uint32_t slot, Allocation *);
+void rsrBindConstant(Context *, Script *, ProgramFragment *, uint32_t slot, Allocation *);
+void rsrBindConstant(Context *, Script *, ProgramVertex*, uint32_t slot, Allocation *);
void rsrBindSampler(Context *, Script *, ProgramFragment *, uint32_t slot, Sampler *);
void rsrBindProgramStore(Context *, Script *, ProgramStore *);
void rsrBindProgramFragment(Context *, Script *, ProgramFragment *);
@@ -68,6 +70,7 @@
void rsrDrawSpriteScreenspace(Context *, Script *,
float x, float y, float z, float w, float h);
void rsrDrawRect(Context *, Script *, float x1, float y1, float x2, float y2, float z);
+void rsrDrawPath(Context *, Script *, Path *);
void rsrDrawMesh(Context *, Script *, Mesh *);
void rsrDrawMeshPrimitive(Context *, Script *, Mesh *, uint32_t primIndex);
void rsrDrawMeshPrimitiveRange(Context *, Script *, Mesh *,
diff --git a/libs/rs/rsScriptC_LibGL.cpp b/libs/rs/rsScriptC_LibGL.cpp
index 7964792..97469d3 100644
--- a/libs/rs/rsScriptC_LibGL.cpp
+++ b/libs/rs/rsScriptC_LibGL.cpp
@@ -50,6 +50,18 @@
pf->bindTexture(rsc, slot, a);
}
+void rsrBindConstant(Context *rsc, Script *sc, ProgramFragment *pf, uint32_t slot, Allocation *a) {
+ CHECK_OBJ_OR_NULL(a);
+ CHECK_OBJ(pf);
+ pf->bindAllocation(rsc, a, slot);
+}
+
+void rsrBindConstant(Context *rsc, Script *sc, ProgramVertex *pv, uint32_t slot, Allocation *a) {
+ CHECK_OBJ_OR_NULL(a);
+ CHECK_OBJ(pv);
+ pv->bindAllocation(rsc, a, slot);
+}
+
void rsrBindSampler(Context *rsc, Script *sc, ProgramFragment *pf, uint32_t slot, Sampler *s) {
CHECK_OBJ_OR_NULL(vs);
CHECK_OBJ(vpf);
@@ -200,6 +212,14 @@
rsrDrawQuad(rsc, sc, x1, y2, z, x2, y2, z, x2, y1, z, x1, y1, z);
}
+void rsrDrawPath(Context *rsc, Script *sc, Path *sm) {
+ CHECK_OBJ(sm);
+ if (!rsc->setupCheck()) {
+ return;
+ }
+ sm->render(rsc);
+}
+
void rsrDrawMesh(Context *rsc, Script *sc, Mesh *sm) {
CHECK_OBJ(sm);
if (!rsc->setupCheck()) {
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index 7966470..70ab7b7 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -46,12 +46,8 @@
delete [] mLODs;
mLODs = NULL;
}
- mDimX = 0;
- mDimY = 0;
- mDimZ = 0;
- mDimLOD = 0;
- mFaces = false;
mElement.clear();
+ memset(&mHal, 0, sizeof(mHal));
}
TypeState::TypeState() {
@@ -62,16 +58,16 @@
}
size_t Type::getOffsetForFace(uint32_t face) const {
- rsAssert(mFaces);
+ rsAssert(mHal.state.faces);
return 0;
}
void Type::compute() {
uint32_t oldLODCount = mLODCount;
- if (mDimLOD) {
- uint32_t l2x = rsFindHighBit(mDimX) + 1;
- uint32_t l2y = rsFindHighBit(mDimY) + 1;
- uint32_t l2z = rsFindHighBit(mDimZ) + 1;
+ if (mHal.state.dimLOD) {
+ uint32_t l2x = rsFindHighBit(mHal.state.dimX) + 1;
+ uint32_t l2y = rsFindHighBit(mHal.state.dimY) + 1;
+ uint32_t l2z = rsFindHighBit(mHal.state.dimZ) + 1;
mLODCount = rsMax(l2x, l2y);
mLODCount = rsMax(mLODCount, l2z);
@@ -85,9 +81,9 @@
mLODs = new LOD[mLODCount];
}
- uint32_t tx = mDimX;
- uint32_t ty = mDimY;
- uint32_t tz = mDimZ;
+ uint32_t tx = mHal.state.dimX;
+ uint32_t ty = mHal.state.dimY;
+ uint32_t tz = mHal.state.dimZ;
size_t offset = 0;
for (uint32_t lod=0; lod < mLODCount; lod++) {
mLODs[lod].mX = tx;
@@ -103,10 +99,11 @@
// At this point the offset is the size of a mipmap chain;
mMipChainSizeBytes = offset;
- if (mFaces) {
+ if (mHal.state.faces) {
offset *= 6;
}
mTotalSizeBytes = offset;
+ mHal.state.element = mElement.get();
}
uint32_t Type::getLODOffset(uint32_t lod, uint32_t x) const {
@@ -127,7 +124,8 @@
return offset;
}
-uint32_t Type::getLODFaceOffset(uint32_t lod, RsAllocationCubemapFace face, uint32_t x, uint32_t y) const {
+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();
@@ -141,7 +139,12 @@
void Type::dumpLOGV(const char *prefix) const {
char buf[1024];
ObjectBase::dumpLOGV(prefix);
- ALOGV("%s Type: x=%zu y=%zu z=%zu mip=%i face=%i", prefix, mDimX, mDimY, mDimZ, mDimLOD, mFaces);
+ ALOGV("%s Type: x=%u y=%u z=%u mip=%i face=%i", prefix,
+ mHal.state.dimX,
+ mHal.state.dimY,
+ mHal.state.dimZ,
+ mHal.state.dimLOD,
+ mHal.state.faces);
snprintf(buf, sizeof(buf), "%s element: ", prefix);
mElement->dumpLOGV(buf);
}
@@ -155,12 +158,12 @@
mElement->serialize(stream);
- stream->addU32(mDimX);
- stream->addU32(mDimY);
- stream->addU32(mDimZ);
+ stream->addU32(mHal.state.dimX);
+ stream->addU32(mHal.state.dimY);
+ stream->addU32(mHal.state.dimZ);
- stream->addU8((uint8_t)(mDimLOD ? 1 : 0));
- stream->addU8((uint8_t)(mFaces ? 1 : 0));
+ stream->addU8((uint8_t)(mHal.state.dimLOD ? 1 : 0));
+ stream->addU8((uint8_t)(mHal.state.faces ? 1 : 0));
}
Type *Type::createFromStream(Context *rsc, IStream *stream) {
@@ -232,11 +235,11 @@
Type *nt = new Type(rsc);
returnRef.set(nt);
nt->mElement.set(e);
- nt->mDimX = dimX;
- nt->mDimY = dimY;
- nt->mDimZ = dimZ;
- nt->mDimLOD = dimLOD;
- nt->mFaces = dimFaces;
+ nt->mHal.state.dimX = dimX;
+ nt->mHal.state.dimY = dimY;
+ nt->mHal.state.dimZ = dimZ;
+ nt->mHal.state.dimLOD = dimLOD;
+ nt->mHal.state.faces = dimFaces;
nt->compute();
ObjectBase::asyncLock();
@@ -248,14 +251,14 @@
ObjectBaseRef<Type> Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const {
return getTypeRef(rsc, mElement.get(), dimX,
- mDimY, mDimZ, mDimLOD, mFaces);
+ mHal.state.dimY, mHal.state.dimZ, mHal.state.dimLOD, mHal.state.faces);
}
ObjectBaseRef<Type> Type::cloneAndResize2D(Context *rsc,
uint32_t dimX,
uint32_t dimY) const {
return getTypeRef(rsc, mElement.get(), dimX, dimY,
- mDimZ, mDimLOD, mFaces);
+ mHal.state.dimZ, mHal.state.dimLOD, mHal.state.faces);
}
@@ -276,8 +279,8 @@
void rsaTypeGetNativeData(RsContext con, RsType type, uint32_t *typeData, uint32_t typeDataSize) {
rsAssert(typeDataSize == 6);
- // Pack the data in the follofing way mDimX; mDimY; mDimZ;
- // mDimLOD; mDimFaces; mElement; into typeData
+ // Pack the data in the follofing way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ;
+ // mHal.state.dimLOD; mHal.state.faces; mElement; into typeData
Type *t = static_cast<Type *>(type);
(*typeData++) = t->getDimX();
diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h
index bc0d9ff..3878156 100644
--- a/libs/rs/rsType.h
+++ b/libs/rs/rsType.h
@@ -22,10 +22,35 @@
// ---------------------------------------------------------------------------
namespace android {
namespace renderscript {
-
+/*****************************************************************************
+ * CAUTION
+ *
+ * Any layout changes for this class may require a corresponding change to be
+ * made to frameworks/compile/libbcc/lib/ScriptCRT/rs_core.c, which contains
+ * a partial copy of the information below.
+ *
+ *****************************************************************************/
class Type : public ObjectBase {
public:
+ struct Hal {
+ mutable void *drv;
+
+ struct State {
+ const Element * element;
+
+ // Size of the structure in the various dimensions. A missing Dimension is
+ // specified as a 0 and not a 1.
+ uint32_t dimX;
+ uint32_t dimY;
+ uint32_t dimZ;
+ bool dimLOD;
+ bool faces;
+ };
+ State state;
+ };
+ Hal mHal;
+
Type * createTex2D(const Element *, size_t w, size_t h, bool mip);
size_t getOffsetForFace(uint32_t face) const;
@@ -34,22 +59,25 @@
size_t getElementSizeBytes() const {return mElement->getSizeBytes();}
const Element * getElement() const {return mElement.get();}
- uint32_t getDimX() const {return mDimX;}
- uint32_t getDimY() const {return mDimY;}
- uint32_t getDimZ() const {return mDimZ;}
- uint32_t getDimLOD() const {return mDimLOD;}
- bool getDimFaces() const {return mFaces;}
+ uint32_t getDimX() const {return mHal.state.dimX;}
+ uint32_t getDimY() const {return mHal.state.dimY;}
+ uint32_t getDimZ() const {return mHal.state.dimZ;}
+ uint32_t getDimLOD() const {return mHal.state.dimLOD;}
+ bool getDimFaces() const {return mHal.state.faces;}
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 getLODFaceOffset(uint32_t lod, RsAllocationCubemapFace face,
+ uint32_t x, uint32_t y) const;
uint32_t getLODCount() const {return mLODCount;}
bool getIsNp2() const;
@@ -95,14 +123,6 @@
ObjectBaseRef<const Element> mElement;
- // Size of the structure in the various dimensions. A missing Dimension is
- // specified as a 0 and not a 1.
- size_t mDimX;
- size_t mDimY;
- size_t mDimZ;
- bool mDimLOD;
- bool mFaces;
-
// count of mipmap levels, 0 indicates no mipmapping
size_t mMipChainSizeBytes;
diff --git a/libs/rs/rs_hal.h b/libs/rs/rs_hal.h
index 0afc94b..1e222e1 100644
--- a/libs/rs/rs_hal.h
+++ b/libs/rs/rs_hal.h
@@ -29,6 +29,7 @@
class Allocation;
class Script;
class ScriptC;
+class Path;
class Program;
class ProgramStore;
class ProgramRaster;
@@ -190,6 +191,13 @@
} mesh;
struct {
+ bool (*initStatic)(const Context *rsc, const Path *m, const Allocation *vtx, const Allocation *loops);
+ bool (*initDynamic)(const Context *rsc, const Path *m);
+ void (*draw)(const Context *rsc, const Path *m);
+ void (*destroy)(const Context *rsc, const Path *m);
+ } path;
+
+ struct {
bool (*init)(const Context *rsc, const Sampler *m);
void (*destroy)(const Context *rsc, const Sampler *m);
} sampler;
diff --git a/libs/rs/scriptc/rs_allocation.rsh b/libs/rs/scriptc/rs_allocation.rsh
index 9ec03bf..a2f69d9 100644
--- a/libs/rs/scriptc/rs_allocation.rsh
+++ b/libs/rs/scriptc/rs_allocation.rsh
@@ -168,5 +168,135 @@
extern const void * __attribute__((overloadable))
rsGetElementAt(rs_allocation, uint32_t x, uint32_t y, uint32_t z);
+/**
+ * @param a allocation to get data from
+ * @return element describing allocation layout
+ */
+extern rs_element __attribute__((overloadable))
+ rsAllocationGetElement(rs_allocation a);
+
+/**
+ * @param m mesh to get data from
+ * @return number of allocations in the mesh that contain vertex
+ * data
+ */
+extern uint32_t __attribute__((overloadable))
+ rsMeshGetVertexAllocationCount(rs_mesh m);
+
+/**
+ * @param m mesh to get data from
+ * @return number of primitive groups in the mesh. This would
+ * include simple primitives as well as allocations
+ * containing index data
+ */
+extern uint32_t __attribute__((overloadable))
+ rsMeshGetPrimitiveCount(rs_mesh m);
+
+/**
+ * @param m mesh to get data from
+ * @param index index of the vertex allocation
+ * @return allocation containing vertex data
+ */
+extern rs_allocation __attribute__((overloadable))
+ rsMeshGetVertexAllocation(rs_mesh m, uint32_t index);
+
+/**
+ * @param m mesh to get data from
+ * @param index index of the index allocation
+ * @return allocation containing index data
+ */
+extern rs_allocation __attribute__((overloadable))
+ rsMeshGetIndexAllocation(rs_mesh m, uint32_t index);
+
+/**
+ * @param m mesh to get data from
+ * @param index index of the primitive
+ * @return primitive describing how the mesh is rendered
+ */
+extern rs_primitive __attribute__((overloadable))
+ rsMeshGetPrimitive(rs_mesh m, uint32_t index);
+
+/**
+ * @param e element to get data from
+ * @return number of sub-elements in this element
+ */
+extern uint32_t __attribute__((overloadable))
+ rsElementGetSubElementCount(rs_element e);
+
+/**
+ * @param e element to get data from
+ * @param index index of the sub-element to return
+ * @return sub-element in this element at given index
+ */
+extern rs_element __attribute__((overloadable))
+ rsElementGetSubElement(rs_element, uint32_t index);
+
+/**
+ * @param e element to get data from
+ * @param index index of the sub-element to return
+ * @return length of the sub-element name including the null
+ * terminator (size of buffer needed to write the name)
+ */
+extern uint32_t __attribute__((overloadable))
+ rsElementGetSubElementNameLength(rs_element e, uint32_t index);
+
+/**
+ * @param e element to get data from
+ * @param index index of the sub-element
+ * @param name array to store the name into
+ * @param nameLength length of the provided name array
+ * @return number of characters actually written, excluding the
+ * null terminator
+ */
+extern uint32_t __attribute__((overloadable))
+ rsElementGetSubElementName(rs_element e, uint32_t index, char *name, uint32_t nameLength);
+
+/**
+ * @param e element to get data from
+ * @param index index of the sub-element
+ * @return array size of sub-element in this element at given
+ * index
+ */
+extern uint32_t __attribute__((overloadable))
+ rsElementGetSubElementArraySize(rs_element e, uint32_t index);
+
+/**
+ * @param e element to get data from
+ * @param index index of the sub-element
+ * @return offset in bytes of sub-element in this element at
+ * given index
+ */
+extern uint32_t __attribute__((overloadable))
+ rsElementGetSubElementOffsetBytes(rs_element e, uint32_t index);
+
+/**
+ * @param e element to get data from
+ * @return total size of the element in bytes
+ */
+extern uint32_t __attribute__((overloadable))
+ rsElementGetSizeBytes(rs_element e);
+
+/**
+ * @param e element to get data from
+ * @return element's data type
+ */
+extern rs_data_type __attribute__((overloadable))
+ rsElementGetDataType(rs_element e);
+
+/**
+ * @param e element to get data from
+ * @return element's data size
+ */
+extern rs_data_kind __attribute__((overloadable))
+ rsElementGetDataKind(rs_element e);
+
+/**
+ * @param e element to get data from
+ * @return length of the element vector (for float2, float3,
+ * etc.)
+ */
+extern uint32_t __attribute__((overloadable))
+ rsElementGetVectorSize(rs_element e);
+
#endif
diff --git a/libs/rs/scriptc/rs_graphics.rsh b/libs/rs/scriptc/rs_graphics.rsh
index 2581953..7fdebdc 100644
--- a/libs/rs/scriptc/rs_graphics.rsh
+++ b/libs/rs/scriptc/rs_graphics.rsh
@@ -22,6 +22,66 @@
*/
#ifndef __RS_GRAPHICS_RSH__
#define __RS_GRAPHICS_RSH__
+
+// These are API 15 once it get official
+typedef enum {
+ RS_DEPTH_FUNC_ALWAYS,
+ RS_DEPTH_FUNC_LESS,
+ RS_DEPTH_FUNC_LEQUAL,
+ RS_DEPTH_FUNC_GREATER,
+ RS_DEPTH_FUNC_GEQUAL,
+ RS_DEPTH_FUNC_EQUAL,
+ RS_DEPTH_FUNC_NOTEQUAL,
+
+ RS_DEPTH_FUNC_INVALID = 100,
+} rs_depth_func;
+
+typedef enum {
+ RS_BLEND_SRC_ZERO, // 0
+ RS_BLEND_SRC_ONE, // 1
+ RS_BLEND_SRC_DST_COLOR, // 2
+ RS_BLEND_SRC_ONE_MINUS_DST_COLOR, // 3
+ RS_BLEND_SRC_SRC_ALPHA, // 4
+ RS_BLEND_SRC_ONE_MINUS_SRC_ALPHA, // 5
+ RS_BLEND_SRC_DST_ALPHA, // 6
+ RS_BLEND_SRC_ONE_MINUS_DST_ALPHA, // 7
+ RS_BLEND_SRC_SRC_ALPHA_SATURATE, // 8
+
+ RS_BLEND_SRC_INVALID = 100,
+} rs_blend_src_func;
+
+typedef enum {
+ RS_BLEND_DST_ZERO, // 0
+ RS_BLEND_DST_ONE, // 1
+ RS_BLEND_DST_SRC_COLOR, // 2
+ RS_BLEND_DST_ONE_MINUS_SRC_COLOR, // 3
+ RS_BLEND_DST_SRC_ALPHA, // 4
+ RS_BLEND_DST_ONE_MINUS_SRC_ALPHA, // 5
+ RS_BLEND_DST_DST_ALPHA, // 6
+ RS_BLEND_DST_ONE_MINUS_DST_ALPHA, // 7
+
+ RS_BLEND_DST_INVALID = 100,
+} rs_blend_dst_func;
+
+typedef enum {
+ RS_CULL_BACK,
+ RS_CULL_FRONT,
+ RS_CULL_NONE,
+
+ RS_CULL_INVALID = 100,
+} rs_cull_mode;
+
+typedef enum {
+ RS_SAMPLER_NEAREST,
+ RS_SAMPLER_LINEAR,
+ RS_SAMPLER_LINEAR_MIP_LINEAR,
+ RS_SAMPLER_WRAP,
+ RS_SAMPLER_CLAMP,
+ RS_SAMPLER_LINEAR_MIP_NEAREST,
+
+ RS_SAMPLER_INVALID = 100,
+} rs_sampler_value;
+
#if (defined(RS_VERSION) && (RS_VERSION >= 14))
/**
* Set the color target used for all subsequent rendering calls
@@ -82,6 +142,88 @@
extern void __attribute__((overloadable))
rsgBindProgramStore(rs_program_store ps);
+
+/**
+ * @hide
+ * Get program store depth function
+ *
+ * @param ps
+ */
+extern rs_depth_func __attribute__((overloadable))
+ rsgProgramStoreGetDepthFunc(rs_program_store ps);
+
+/**
+ * @hide
+ * Get program store depth mask
+ *
+ * @param ps
+ */
+extern bool __attribute__((overloadable))
+ rsgProgramStoreGetDepthMask(rs_program_store ps);
+/**
+ * @hide
+ * Get program store red component color mask
+ *
+ * @param ps
+ */
+extern bool __attribute__((overloadable))
+ rsgProgramStoreGetColorMaskR(rs_program_store ps);
+
+/**
+ * @hide
+ * Get program store green component color mask
+ *
+ * @param ps
+ */
+extern bool __attribute__((overloadable))
+ rsgProgramStoreGetColorMaskG(rs_program_store ps);
+
+/**
+ * @hide
+ * Get program store blur component color mask
+ *
+ * @param ps
+ */
+extern bool __attribute__((overloadable))
+ rsgProgramStoreGetColorMaskB(rs_program_store ps);
+
+/**
+ * @hide
+ * Get program store alpha component color mask
+ *
+ * @param ps
+ */
+extern bool __attribute__((overloadable))
+ rsgProgramStoreGetColorMaskA(rs_program_store ps);
+
+/**
+ * @hide
+ * Get program store blend source function
+ *
+ * @param ps
+ */
+extern rs_blend_src_func __attribute__((overloadable))
+ rsgProgramStoreGetBlendSrcFunc(rs_program_store ps);
+
+/**
+ * @hide
+ * Get program store blend destination function
+ *
+ * @param ps
+ */
+extern rs_blend_dst_func __attribute__((overloadable))
+ rsgProgramStoreGetBlendDstFunc(rs_program_store ps);
+
+/**
+ * @hide
+ * Get program store dither state
+ *
+ * @param ps
+ */
+extern bool __attribute__((overloadable))
+ rsgProgramStoreGetDitherEnabled(rs_program_store ps);
+
+
/**
* Bind a new ProgramVertex to the rendering context.
*
@@ -99,6 +241,24 @@
rsgBindProgramRaster(rs_program_raster pr);
/**
+ * @hide
+ * Get program raster point sprite state
+ *
+ * @param pr
+ */
+extern bool __attribute__((overloadable))
+ rsgProgramRasterGetPointSpriteEnabled(rs_program_raster pr);
+
+/**
+ * @hide
+ * Get program raster cull mode
+ *
+ * @param pr
+ */
+extern rs_cull_mode __attribute__((overloadable))
+ rsgProgramRasterGetCullMode(rs_program_raster pr);
+
+/**
* Bind a new Sampler object to a ProgramFragment. The sampler will
* operate on the texture bound at the matching slot.
*
@@ -108,6 +268,51 @@
rsgBindSampler(rs_program_fragment, uint slot, rs_sampler);
/**
+ * @hide
+ * Get sampler minification value
+ *
+ * @param pr
+ */
+extern rs_sampler_value __attribute__((overloadable))
+ rsgSamplerGetMinification(rs_sampler s);
+
+/**
+ * @hide
+ * Get sampler magnification value
+ *
+ * @param pr
+ */
+extern rs_sampler_value __attribute__((overloadable))
+ rsgSamplerGetMagnification(rs_sampler s);
+
+/**
+ * @hide
+ * Get sampler wrap S value
+ *
+ * @param pr
+ */
+extern rs_sampler_value __attribute__((overloadable))
+ rsgSamplerGetWrapS(rs_sampler s);
+
+/**
+ * @hide
+ * Get sampler wrap T value
+ *
+ * @param pr
+ */
+extern rs_sampler_value __attribute__((overloadable))
+ rsgSamplerGetWrapT(rs_sampler s);
+
+/**
+ * @hide
+ * Get sampler anisotropy
+ *
+ * @param pr
+ */
+extern float __attribute__((overloadable))
+ rsgSamplerGetAnisotropy(rs_sampler s);
+
+/**
* Bind a new Allocation object to a ProgramFragment. The
* Allocation must be a valid texture for the Program. The sampling
* of the texture will be controled by the Sampler bound at the
@@ -164,6 +369,28 @@
rsgProgramFragmentConstantColor(rs_program_fragment pf, float r, float g, float b, float a);
/**
+ * Bind a new Allocation object to a ProgramFragment. The
+ * Allocation must be a valid constant input for the Program.
+ *
+ * @param ps program object
+ * @param slot index of the constant buffer on the program
+ * @param c constants to bind
+ */
+extern void __attribute__((overloadable))
+ rsgBindConstant(rs_program_fragment ps, uint slot, rs_allocation c);
+
+/**
+ * Bind a new Allocation object to a ProgramVertex. The
+ * Allocation must be a valid constant input for the Program.
+ *
+ * @param pv program object
+ * @param slot index of the constant buffer on the program
+ * @param c constants to bind
+ */
+extern void __attribute__((overloadable))
+ rsgBindConstant(rs_program_vertex pv, uint slot, rs_allocation c);
+
+/**
* Get the width of the current rendering surface.
*
* @return uint
@@ -288,6 +515,9 @@
extern void __attribute__((overloadable))
rsgDrawSpriteScreenspace(float x, float y, float z, float w, float h);
+extern void __attribute__((overloadable))
+ rsgDrawPath(rs_path p);
+
/**
* Draw a mesh using the current context state. The whole mesh is
* rendered.
diff --git a/libs/rs/scriptc/rs_object.rsh b/libs/rs/scriptc/rs_object.rsh
index a431219..1fc3f83 100644
--- a/libs/rs/scriptc/rs_object.rsh
+++ b/libs/rs/scriptc/rs_object.rsh
@@ -56,6 +56,11 @@
* \overload
*/
extern void __attribute__((overloadable))
+ rsSetObject(rs_path *dst, rs_path src);
+/**
+ * \overload
+ */
+extern void __attribute__((overloadable))
rsSetObject(rs_mesh *dst, rs_mesh src);
/**
* \overload
@@ -114,6 +119,11 @@
* \overload
*/
extern void __attribute__((overloadable))
+ rsClearObject(rs_path *dst);
+/**
+ * \overload
+ */
+extern void __attribute__((overloadable))
rsClearObject(rs_mesh *dst);
/**
* \overload
@@ -175,6 +185,11 @@
* \overload
*/
extern bool __attribute__((overloadable))
+ rsIsObject(rs_path);
+/**
+ * \overload
+ */
+extern bool __attribute__((overloadable))
rsIsObject(rs_mesh);
/**
* \overload
diff --git a/libs/rs/scriptc/rs_types.rsh b/libs/rs/scriptc/rs_types.rsh
index 84bca9c..5345a48 100644
--- a/libs/rs/scriptc/rs_types.rsh
+++ b/libs/rs/scriptc/rs_types.rsh
@@ -138,6 +138,12 @@
*/
typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_mesh;
/**
+ * \brief Opaque handle to a Renderscript Path object.
+ *
+ * See: android.renderscript.Path
+ */
+typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_path;
+/**
* \brief Opaque handle to a Renderscript ProgramFragment object.
*
* See: android.renderscript.ProgramFragment
@@ -396,4 +402,96 @@
#endif //defined(RS_VERSION) && (RS_VERSION >= 14)
+/**
+ * Describes the way mesh vertex data is interpreted when rendering
+ *
+ **/
+typedef enum {
+ RS_PRIMITIVE_POINT,
+ RS_PRIMITIVE_LINE,
+ RS_PRIMITIVE_LINE_STRIP,
+ RS_PRIMITIVE_TRIANGLE,
+ RS_PRIMITIVE_TRIANGLE_STRIP,
+ RS_PRIMITIVE_TRIANGLE_FAN,
+
+ RS_PRIMITIVE_INVALID = 100,
+} rs_primitive;
+
+/**
+ * \brief Enumeration for possible element data types
+ *
+ * DataType represents the basic type information for a basic element. The
+ * naming convention follows. For numeric types it is FLOAT,
+ * SIGNED, or UNSIGNED followed by the _BITS where BITS is the
+ * size of the data. BOOLEAN is a true / false (1,0)
+ * represented in an 8 bit container. The UNSIGNED variants
+ * with multiple bit definitions are for packed graphical data
+ * formats and represent vectors with per vector member sizes
+ * which are treated as a single unit for packing and alignment
+ * purposes.
+ *
+ * MATRIX the three matrix types contain FLOAT_32 elements and are treated
+ * as 32 bits for alignment purposes.
+ *
+ * RS_* objects. 32 bit opaque handles.
+ */
+typedef enum {
+ RS_TYPE_NONE,
+ //RS_TYPE_FLOAT_16,
+ RS_TYPE_FLOAT_32 = 2,
+ RS_TYPE_FLOAT_64,
+ RS_TYPE_SIGNED_8,
+ RS_TYPE_SIGNED_16,
+ RS_TYPE_SIGNED_32,
+ RS_TYPE_SIGNED_64,
+ RS_TYPE_UNSIGNED_8,
+ RS_TYPE_UNSIGNED_16,
+ RS_TYPE_UNSIGNED_32,
+ RS_TYPE_UNSIGNED_64,
+
+ RS_TYPE_BOOLEAN,
+
+ RS_TYPE_UNSIGNED_5_6_5,
+ RS_TYPE_UNSIGNED_5_5_5_1,
+ RS_TYPE_UNSIGNED_4_4_4_4,
+
+ RS_TYPE_MATRIX_4X4,
+ RS_TYPE_MATRIX_3X3,
+ RS_TYPE_MATRIX_2X2,
+
+ RS_TYPE_ELEMENT = 1000,
+ RS_TYPE_TYPE,
+ RS_TYPE_ALLOCATION,
+ RS_TYPE_SAMPLER,
+ RS_TYPE_SCRIPT,
+ RS_TYPE_MESH,
+ RS_TYPE_PROGRAM_FRAGMENT,
+ RS_TYPE_PROGRAM_VERTEX,
+ RS_TYPE_PROGRAM_RASTER,
+ RS_TYPE_PROGRAM_STORE,
+
+ RS_TYPE_INVALID = 10000,
+} rs_data_type;
+
+/**
+ * \brief Enumeration for possible element data kind
+ *
+ * The special interpretation of the data if required. This is primarly
+ * useful for graphical data. USER indicates no special interpretation is
+ * expected. PIXEL is used in conjunction with the standard data types for
+ * representing texture formats.
+ */
+typedef enum {
+ RS_KIND_USER,
+
+ RS_KIND_PIXEL_L = 7,
+ RS_KIND_PIXEL_A,
+ RS_KIND_PIXEL_LA,
+ RS_KIND_PIXEL_RGB,
+ RS_KIND_PIXEL_RGBA,
+ RS_KIND_PIXEL_DEPTH,
+
+ RS_KIND_INVALID = 100,
+} rs_data_kind;
+
#endif
diff --git a/media/java/android/media/MediaInserter.java b/media/java/android/media/MediaInserter.java
index e92c710..7fcbffa 100644
--- a/media/java/android/media/MediaInserter.java
+++ b/media/java/android/media/MediaInserter.java
@@ -34,6 +34,8 @@
public class MediaInserter {
private final HashMap<Uri, List<ContentValues>> mRowMap =
new HashMap<Uri, List<ContentValues>>();
+ private final HashMap<Uri, List<ContentValues>> mPriorityRowMap =
+ new HashMap<Uri, List<ContentValues>>();
private IContentProvider mProvider;
private int mBufferSizePerUri;
@@ -44,26 +46,45 @@
}
public void insert(Uri tableUri, ContentValues values) throws RemoteException {
- List<ContentValues> list = mRowMap.get(tableUri);
+ insert(tableUri, values, false);
+ }
+
+ public void insertwithPriority(Uri tableUri, ContentValues values) throws RemoteException {
+ insert(tableUri, values, true);
+ }
+
+ private void insert(Uri tableUri, ContentValues values, boolean priority) throws RemoteException {
+ HashMap<Uri, List<ContentValues>> rowmap = priority ? mPriorityRowMap : mRowMap;
+ List<ContentValues> list = rowmap.get(tableUri);
if (list == null) {
list = new ArrayList<ContentValues>();
- mRowMap.put(tableUri, list);
+ rowmap.put(tableUri, list);
}
list.add(new ContentValues(values));
if (list.size() >= mBufferSizePerUri) {
- flush(tableUri);
+ flushAllPriority();
+ flush(tableUri, list);
}
}
public void flushAll() throws RemoteException {
+ flushAllPriority();
for (Uri tableUri : mRowMap.keySet()){
- flush(tableUri);
+ List<ContentValues> list = mRowMap.get(tableUri);
+ flush(tableUri, list);
}
mRowMap.clear();
}
- private void flush(Uri tableUri) throws RemoteException {
- List<ContentValues> list = mRowMap.get(tableUri);
+ private void flushAllPriority() throws RemoteException {
+ for (Uri tableUri : mPriorityRowMap.keySet()){
+ List<ContentValues> list = mPriorityRowMap.get(tableUri);
+ flush(tableUri, list);
+ }
+ mPriorityRowMap.clear();
+ }
+
+ private void flush(Uri tableUri, List<ContentValues> list) throws RemoteException {
if (!list.isEmpty()) {
ContentValues[] valuesArray = new ContentValues[list.size()];
valuesArray = list.toArray(valuesArray);
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 69ca58b..52d31c7 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -59,6 +59,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.Locale;
/**
@@ -374,7 +375,7 @@
// hashes file path to FileCacheEntry.
// path should be lower case if mCaseInsensitivePaths is true
- private HashMap<String, FileCacheEntry> mFileCache;
+ private LinkedHashMap<String, FileCacheEntry> mFileCache;
private ArrayList<FileCacheEntry> mPlayLists;
@@ -922,16 +923,15 @@
}
}
- // new file, insert it
- // We insert directories immediately to ensure they are in the database
- // before the files they contain.
- // Otherwise we can get duplicate directory entries in the database
- // if one of the media FileInserters is flushed before the files table FileInserter
- // Also, we immediately insert the file if the rowId of the inserted file is
- // needed.
- if (inserter == null || needToSetSettings ||
- entry.mFormat == MtpConstants.FORMAT_ASSOCIATION) {
+ // New file, insert it.
+ // Directories need to be inserted before the files they contain, so they
+ // get priority when bulk inserting.
+ // If the rowId of the inserted file is needed, it gets inserted immediately,
+ // bypassing the bulk inserter.
+ if (inserter == null || needToSetSettings) {
result = mMediaProvider.insert(tableUri, values);
+ } else if (entry.mFormat == MtpConstants.FORMAT_ASSOCIATION) {
+ inserter.insertwithPriority(tableUri, values);
} else {
inserter.insert(tableUri, values);
}
@@ -1029,7 +1029,7 @@
String[] selectionArgs = null;
if (mFileCache == null) {
- mFileCache = new HashMap<String, FileCacheEntry>();
+ mFileCache = new LinkedHashMap<String, FileCacheEntry>();
} else {
mFileCache.clear();
}
@@ -1151,7 +1151,8 @@
}
static class MediaBulkDeleter {
- StringBuilder idList = new StringBuilder();
+ StringBuilder whereClause = new StringBuilder();
+ ArrayList<String> whereArgs = new ArrayList<String>(100);
IContentProvider mProvider;
Uri mBaseUri;
@@ -1161,19 +1162,26 @@
}
public void delete(long id) throws RemoteException {
- if (idList.length() != 0) {
- idList.append(",");
+ if (whereClause.length() != 0) {
+ whereClause.append(",");
}
- idList.append(id);
- if (idList.length() > 1024) {
+ whereClause.append("?");
+ whereArgs.add("" + id);
+ if (whereArgs.size() > 100) {
flush();
}
}
public void flush() throws RemoteException {
- int numrows = mProvider.delete(mBaseUri, MediaStore.MediaColumns._ID + " IN (" +
- idList.toString() + ")", null);
- //Log.i("@@@@@@@@@", "rows deleted: " + numrows);
- idList.setLength(0);
+ int size = whereArgs.size();
+ if (size > 0) {
+ String [] foo = new String [size];
+ foo = whereArgs.toArray(foo);
+ int numrows = mProvider.delete(mBaseUri, MediaStore.MediaColumns._ID + " IN (" +
+ whereClause.toString() + ")", foo);
+ //Log.i("@@@@@@@@@", "rows deleted: " + numrows);
+ whereClause.setLength(0);
+ whereArgs.clear();
+ }
}
}
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index df4fbb5..ceb87db 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -623,7 +623,7 @@
newTrack->setVolume(leftVolume, rightVolume);
newTrack->setLoop(0, frameCount, loop);
- // From now on, AudioTrack callbacks recevieved with previous toggle value will be ignored.
+ // From now on, AudioTrack callbacks received with previous toggle value will be ignored.
mToggle = toggle;
mAudioTrack = newTrack;
mPos = 0;
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index 4d94a75..098a1a2 100755
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -1298,7 +1298,7 @@
return -EINVAL;
}
- Session_GetConfig(effect->session, (effect_config_t *)pCmdData);
+ Session_GetConfig(effect->session, (effect_config_t *)pReplyData);
break;
case EFFECT_CMD_SET_CONFIG_REVERSE:
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index b74b3e3..a4068ff 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -304,10 +304,25 @@
if (mActive == 0) {
mActive = 1;
+ pid_t tid;
+ if (t != 0) {
+ mReadyToRun = WOULD_BLOCK;
+ t->run("ClientRecordThread", ANDROID_PRIORITY_AUDIO);
+ tid = t->getTid(); // pid_t is unknown until run()
+ ALOGV("getTid=%d", tid);
+ if (tid == -1) {
+ tid = 0;
+ }
+ // thread blocks in readyToRun()
+ } else {
+ tid = 0; // not gettid()
+ }
+
cblk->lock.lock();
if (!(cblk->flags & CBLK_INVALID_MSK)) {
cblk->lock.unlock();
- ret = mAudioRecord->start();
+ ALOGV("mAudioRecord->start(tid=%d)", tid);
+ ret = mAudioRecord->start(tid);
cblk->lock.lock();
if (ret == DEAD_OBJECT) {
android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
@@ -322,7 +337,9 @@
cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
cblk->waitTimeMs = 0;
if (t != 0) {
- t->run("ClientRecordThread", ANDROID_PRIORITY_AUDIO);
+ // thread unblocks in readyToRun() and returns NO_ERROR
+ mReadyToRun = NO_ERROR;
+ mCondition.signal();
} else {
mPreviousPriority = getpriority(PRIO_PROCESS, 0);
mPreviousSchedulingGroup = androidGetThreadSchedulingGroup(0);
@@ -330,6 +347,9 @@
}
} else {
mActive = 0;
+ // thread unblocks in readyToRun() and returns NO_INIT
+ mReadyToRun = NO_INIT;
+ mCondition.signal();
}
}
@@ -522,7 +542,7 @@
ALOGW( "obtainBuffer timed out (is the CPU pegged?) "
"user=%08x, server=%08x", cblk->user, cblk->server);
cblk->lock.unlock();
- result = mAudioRecord->start();
+ result = mAudioRecord->start(0); // callback thread hasn't changed
cblk->lock.lock();
if (result == DEAD_OBJECT) {
android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
@@ -760,7 +780,7 @@
result = openRecord_l(cblk->sampleRate, mFormat, mChannelMask,
mFrameCount, mFlags, getInput_l());
if (result == NO_ERROR) {
- result = mAudioRecord->start();
+ result = mAudioRecord->start(0); // callback thread hasn't changed
}
if (result != NO_ERROR) {
mActive = false;
@@ -811,6 +831,15 @@
return mReceiver.processAudioBuffer(this);
}
+status_t AudioRecord::ClientRecordThread::readyToRun()
+{
+ AutoMutex(mReceiver.mLock);
+ while (mReceiver.mReadyToRun == WOULD_BLOCK) {
+ mReceiver.mCondition.wait(mReceiver.mLock);
+ }
+ return mReceiver.mReadyToRun;
+}
+
// -------------------------------------------------------------------------
}; // namespace android
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 087d7b2..aead9a1 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -1,4 +1,4 @@
-/* frameworks/base/media/libmedia/AudioTrack.cpp
+/*
**
** Copyright 2007, The Android Open Source Project
**
@@ -362,18 +362,26 @@
cblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
cblk->waitTimeMs = 0;
android_atomic_and(~CBLK_DISABLED_ON, &cblk->flags);
+ pid_t tid;
if (t != 0) {
t->run("AudioTrackThread", ANDROID_PRIORITY_AUDIO);
+ tid = t->getTid(); // pid_t is unknown until run()
+ ALOGV("getTid=%d", tid);
+ if (tid == -1) {
+ tid = 0;
+ }
} else {
mPreviousPriority = getpriority(PRIO_PROCESS, 0);
mPreviousSchedulingGroup = androidGetThreadSchedulingGroup(0);
androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
+ tid = 0; // not gettid()
}
ALOGV("start %p before lock cblk %p", this, mCblk);
if (!(cblk->flags & CBLK_INVALID_MSK)) {
cblk->lock.unlock();
- status = mAudioTrack->start();
+ ALOGV("mAudioTrack->start(tid=%d)", tid);
+ status = mAudioTrack->start(tid);
cblk->lock.lock();
if (status == DEAD_OBJECT) {
android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
@@ -591,26 +599,6 @@
return NO_ERROR;
}
-status_t AudioTrack::getLoop(uint32_t *loopStart, uint32_t *loopEnd, int *loopCount) const
-{
- AutoMutex lock(mLock);
- if (loopStart != NULL) {
- *loopStart = mCblk->loopStart;
- }
- if (loopEnd != NULL) {
- *loopEnd = mCblk->loopEnd;
- }
- if (loopCount != NULL) {
- if (mCblk->loopCount < 0) {
- *loopCount = -1;
- } else {
- *loopCount = mCblk->loopCount;
- }
- }
-
- return NO_ERROR;
-}
-
status_t AudioTrack::setMarkerPosition(uint32_t marker)
{
if (mCbf == NULL) return INVALID_OPERATION;
@@ -784,7 +772,7 @@
}
}
} else {
- // Ensure that buffer alignment matches channelcount
+ // Ensure that buffer alignment matches channelCount
int channelCount = popcount(channelMask);
if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) {
ALOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount);
@@ -895,7 +883,7 @@
"user=%08x, server=%08x", this, cblk->user, cblk->server);
//unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140)
cblk->lock.unlock();
- result = mAudioTrack->start();
+ result = mAudioTrack->start(0); // callback thread hasn't changed
cblk->lock.lock();
if (result == DEAD_OBJECT) {
android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
@@ -927,7 +915,7 @@
if (mActive && (cblk->flags & CBLK_DISABLED_MSK)) {
android_atomic_and(~CBLK_DISABLED_ON, &cblk->flags);
ALOGW("obtainBuffer() track %p disabled, restarting", this);
- mAudioTrack->start();
+ mAudioTrack->start(0); // callback thread hasn't changed
}
cblk->waitTimeMs = 0;
@@ -971,7 +959,8 @@
if (mSharedBuffer != 0) return INVALID_OPERATION;
if (ssize_t(userSize) < 0) {
- // sanity-check. user is most-likely passing an error code.
+ // Sanity-check: user is most-likely passing an error code, and it would
+ // make the return value ambiguous (actualSize vs error).
ALOGE("AudioTrack::write(buffer=%p, size=%u (%d)",
buffer, userSize, userSize);
return BAD_VALUE;
@@ -994,8 +983,6 @@
do {
audioBuffer.frameCount = userSize/frameSz;
- // Calling obtainBuffer() with a negative wait count causes
- // an (almost) infinite wait time.
status_t err = obtainBuffer(&audioBuffer, -1);
if (err < 0) {
// out of buffers, return #bytes written
@@ -1085,6 +1072,9 @@
frames = mRemainingFrames;
}
+ // See description of waitCount parameter at declaration of obtainBuffer().
+ // The logic below prevents us from being stuck below at obtainBuffer()
+ // not being able to handle timed events (position, markers, loops).
int32_t waitCount = -1;
if (mUpdatePeriod || (!mMarkerReached && mMarkerPosition) || mLoopCount) {
waitCount = 1;
@@ -1094,9 +1084,6 @@
audioBuffer.frameCount = frames;
- // Calling obtainBuffer() with a wait count of 1
- // limits wait time to WAIT_PERIOD_MS. This prevents from being
- // stuck here not being able to handle timed events (position, markers, loops).
status_t err = obtainBuffer(&audioBuffer, waitCount);
if (err < NO_ERROR) {
if (err != TIMED_OUT) {
@@ -1218,7 +1205,7 @@
}
}
if (mActive) {
- result = mAudioTrack->start();
+ result = mAudioTrack->start(0); // callback thread hasn't changed
ALOGW_IF(result != NO_ERROR, "restoreTrack_l() start() failed status %d", result);
}
if (fromStart && result == NO_ERROR) {
diff --git a/media/libmedia/IAudioRecord.cpp b/media/libmedia/IAudioRecord.cpp
index 8c7a960..6b473c9 100644
--- a/media/libmedia/IAudioRecord.cpp
+++ b/media/libmedia/IAudioRecord.cpp
@@ -42,10 +42,11 @@
{
}
- virtual status_t start()
+ virtual status_t start(pid_t tid)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor());
+ data.writeInt32(tid);
status_t status = remote()->transact(START, data, &reply);
if (status == NO_ERROR) {
status = reply.readInt32();
@@ -90,7 +91,7 @@
} break;
case START: {
CHECK_INTERFACE(IAudioRecord, data, reply);
- reply->writeInt32(start());
+ reply->writeInt32(start(data.readInt32()));
return NO_ERROR;
} break;
case STOP: {
diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp
index e618619..a7958de 100644
--- a/media/libmedia/IAudioTrack.cpp
+++ b/media/libmedia/IAudioTrack.cpp
@@ -1,4 +1,4 @@
-/* //device/extlibs/pv/android/IAudioTrack.cpp
+/*
**
** Copyright 2007, The Android Open Source Project
**
@@ -58,10 +58,11 @@
return cblk;
}
- virtual status_t start()
+ virtual status_t start(pid_t tid)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ data.writeInt32(tid);
status_t status = remote()->transact(START, data, &reply);
if (status == NO_ERROR) {
status = reply.readInt32();
@@ -130,7 +131,7 @@
} break;
case START: {
CHECK_INTERFACE(IAudioTrack, data, reply);
- reply->writeInt32(start());
+ reply->writeInt32(start(data.readInt32()));
return NO_ERROR;
} break;
case STOP: {
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 6cb10aa..54eb98a 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -791,7 +791,7 @@
// generators, instantiates output audio track.
//
// Input:
-// streamType: Type of stream used for tone playback (enum AudioTrack::stream_type)
+// streamType: Type of stream used for tone playback
// volume: volume applied to tone (0.0 to 1.0)
//
// Output:
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index f1c47dd..250425b 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -1,4 +1,4 @@
-/* mediaplayer.cpp
+/*
**
** Copyright 2006, The Android Open Source Project
**
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index a0c20ae..4df7f3d 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1265,6 +1265,8 @@
mStreamType = AUDIO_STREAM_MUSIC;
mLeftVolume = 1.0;
mRightVolume = 1.0;
+ mPlaybackRatePermille = 1000;
+ mSampleRateHz = 0;
mLatency = 0;
mMsecsPerFrame = 0;
mAuxEffectId = 0;
@@ -1402,10 +1404,15 @@
ALOGV("setVolume");
t->setVolume(mLeftVolume, mRightVolume);
- mMsecsPerFrame = 1.e3 / (float) sampleRate;
+ mSampleRateHz = sampleRate;
+ mMsecsPerFrame = mPlaybackRatePermille / (float) sampleRate;
mLatency = t->latency();
mTrack = t;
+ status_t res = t->setSampleRate(mPlaybackRatePermille * mSampleRateHz / 1000);
+ if (res != NO_ERROR) {
+ return res;
+ }
t->setAuxEffectSendLevel(mSendLevel);
return t->attachAuxEffect(mAuxEffectId);;
}
@@ -1469,6 +1476,22 @@
}
}
+status_t MediaPlayerService::AudioOutput::setPlaybackRatePermille(int32_t ratePermille)
+{
+ ALOGV("setPlaybackRatePermille(%d)", ratePermille);
+ status_t res = NO_ERROR;
+ if (mTrack) {
+ res = mTrack->setSampleRate(ratePermille * mSampleRateHz / 1000);
+ } else {
+ res = NO_INIT;
+ }
+ mPlaybackRatePermille = ratePermille;
+ if (mSampleRateHz != 0) {
+ mMsecsPerFrame = mPlaybackRatePermille / (float) mSampleRateHz;
+ }
+ return res;
+}
+
status_t MediaPlayerService::AudioOutput::setAuxEffectSendLevel(float level)
{
ALOGV("setAuxEffectSendLevel(%f)", level);
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index fa71d11..52af64d 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -95,6 +95,7 @@
virtual void close();
void setAudioStreamType(audio_stream_type_t streamType) { mStreamType = streamType; }
void setVolume(float left, float right);
+ virtual status_t setPlaybackRatePermille(int32_t ratePermille);
status_t setAuxEffectSendLevel(float level);
status_t attachAuxEffect(int effectId);
virtual status_t dump(int fd, const Vector<String16>& args) const;
@@ -112,6 +113,8 @@
audio_stream_type_t mStreamType;
float mLeftVolume;
float mRightVolume;
+ int32_t mPlaybackRatePermille;
+ uint32_t mSampleRateHz; // sample rate of the content, as set in open()
float mMsecsPerFrame;
uint32_t mLatency;
int mSessionId;
@@ -152,6 +155,7 @@
virtual void close() {}
void setAudioStreamType(audio_stream_type_t streamType) {}
void setVolume(float left, float right) {}
+ virtual status_t setPlaybackRatePermille(int32_t ratePermille) { return INVALID_OPERATION; }
uint32_t sampleRate() const { return mSampleRate; }
audio_format_t format() const { return mFormat; }
size_t size() const { return mSize; }
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
index 6d7771a..052ebf0 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -176,7 +176,7 @@
}
status_t StagefrightPlayer::setParameter(int key, const Parcel &request) {
- ALOGV("setParameter");
+ ALOGV("setParameter(key=%d)", key);
return mPlayer->setParameter(key, request);
}
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index 9a9c3ef..df27566 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -268,6 +268,16 @@
return mReachedEOS;
}
+status_t AudioPlayer::setPlaybackRatePermille(int32_t ratePermille) {
+ if (mAudioSink.get() != NULL) {
+ return mAudioSink->setPlaybackRatePermille(ratePermille);
+ } else if (mAudioTrack != NULL){
+ return mAudioTrack->setSampleRate(ratePermille * mSampleRate / 1000);
+ } else {
+ return NO_INIT;
+ }
+}
+
// static
size_t AudioPlayer::AudioSinkCallback(
MediaPlayerBase::AudioSink *audioSink,
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 85b7979..70945e3 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -2251,6 +2251,14 @@
{
return setCacheStatCollectFreq(request);
}
+ case KEY_PARAMETER_PLAYBACK_RATE_PERMILLE:
+ {
+ if (mAudioPlayer != NULL) {
+ return mAudioPlayer->setPlaybackRatePermille(request.readInt32());
+ } else {
+ return NO_INIT;
+ }
+ }
default:
{
return ERROR_UNSUPPORTED;
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 06be2ef..0b1016c 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -118,12 +118,6 @@
// ----------------------------------------------------------------------------
-Loader::entry_t::entry_t(int dpy, int impl, const char* tag)
- : dpy(dpy), impl(impl), tag(tag) {
-}
-
-// ----------------------------------------------------------------------------
-
Loader::Loader()
{
char line[256];
@@ -131,8 +125,9 @@
/* Special case for GLES emulation */
if (checkGlesEmulationStatus() == 0) {
- ALOGD("Emulator without GPU support detected. Fallback to software renderer.");
- gConfig.add( entry_t(0, 0, "android") );
+ ALOGD("Emulator without GPU support detected. "
+ "Fallback to software renderer.");
+ mDriverTag.setTo("android");
return;
}
@@ -141,14 +136,16 @@
if (cfg == NULL) {
// default config
ALOGD("egl.cfg not found, using default config");
- gConfig.add( entry_t(0, 0, "android") );
+ mDriverTag.setTo("android");
} else {
while (fgets(line, 256, cfg)) {
- int dpy;
- int impl;
+ int dpy, impl;
if (sscanf(line, "%u %u %s", &dpy, &impl, tag) == 3) {
//ALOGD(">>> %u %u %s", dpy, impl, tag);
- gConfig.add( entry_t(dpy, impl, tag) );
+ // We only load the h/w accelerated implementation
+ if (tag != String8("android")) {
+ mDriverTag = tag;
+ }
}
}
fclose(cfg);
@@ -160,30 +157,12 @@
GLTrace_stop();
}
-const char* Loader::getTag(int dpy, int impl)
+void* Loader::open(egl_connection_t* cnx)
{
- const Vector<entry_t>& cfgs(gConfig);
- const size_t c = cfgs.size();
- for (size_t i=0 ; i<c ; i++) {
- if (dpy == cfgs[i].dpy)
- if (impl == cfgs[i].impl)
- return cfgs[i].tag.string();
- }
- return 0;
-}
-
-void* Loader::open(EGLNativeDisplayType display, int impl, egl_connection_t* cnx)
-{
- /*
- * TODO: if we don't find display/0, then use 0/0
- * (0/0 should always work)
- */
-
void* dso;
- int index = int(display);
driver_t* hnd = 0;
- char const* tag = getTag(index, impl);
+ char const* tag = mDriverTag.string();
if (tag) {
dso = load_driver("GLES", tag, cnx, EGL | GLESv1_CM | GLESv2);
if (dso) {
@@ -193,16 +172,14 @@
dso = load_driver("EGL", tag, cnx, EGL);
if (dso) {
hnd = new driver_t(dso);
-
// TODO: make this more automated
hnd->set( load_driver("GLESv1_CM", tag, cnx, GLESv1_CM), GLESv1_CM );
-
- hnd->set( load_driver("GLESv2", tag, cnx, GLESv2), GLESv2 );
+ hnd->set( load_driver("GLESv2", tag, cnx, GLESv2), GLESv2 );
}
}
}
- LOG_FATAL_IF(!index && !impl && !hnd,
+ LOG_FATAL_IF(!index && !hnd,
"couldn't find the default OpenGL ES implementation "
"for default display");
@@ -221,7 +198,7 @@
__eglMustCastToProperFunctionPointerType* curr,
getProcAddressType getProcAddress)
{
- const size_t SIZE = 256;
+ const ssize_t SIZE = 256;
char scrap[SIZE];
while (*api) {
char const * name = *api;
@@ -326,14 +303,14 @@
if (mask & GLESv1_CM) {
init_api(dso, gl_names,
(__eglMustCastToProperFunctionPointerType*)
- &cnx->hooks[GLESv1_INDEX]->gl,
+ &cnx->hooks[egl_connection_t::GLESv1_INDEX]->gl,
getProcAddress);
}
if (mask & GLESv2) {
init_api(dso, gl_names,
(__eglMustCastToProperFunctionPointerType*)
- &cnx->hooks[GLESv2_INDEX]->gl,
+ &cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl,
getProcAddress);
}
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 580d6e4..30773cb 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -24,7 +24,6 @@
#include <utils/Errors.h>
#include <utils/Singleton.h>
#include <utils/String8.h>
-#include <utils/Vector.h>
#include <EGL/egl.h>
@@ -53,23 +52,13 @@
void* dso[3];
};
- struct entry_t {
- entry_t() { }
- entry_t(int dpy, int impl, const char* tag);
- int dpy;
- int impl;
- String8 tag;
- };
-
- Vector<entry_t> gConfig;
+ String8 mDriverTag;
getProcAddressType getProcAddress;
- const char* getTag(int dpy, int impl);
-
public:
~Loader();
- void* open(EGLNativeDisplayType display, int impl, egl_connection_t* cnx);
+ void* open(egl_connection_t* cnx);
status_t close(void* driver);
private:
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 83933e5..4a56dcf 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -48,8 +48,8 @@
namespace android {
// ----------------------------------------------------------------------------
-egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
-gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
+egl_connection_t gEGLImpl;
+gl_hooks_t gHooks[2];
gl_hooks_t gHooksNoContext;
pthread_key_t gGLWrapperKey = -1;
@@ -187,16 +187,13 @@
return dp;
}
-egl_connection_t* validate_display_config(EGLDisplay dpy, EGLConfig config,
+egl_connection_t* validate_display_config(EGLDisplay dpy, EGLConfig,
egl_display_t const*& dp) {
dp = validate_display(dpy);
if (!dp)
return (egl_connection_t*) NULL;
- if (intptr_t(config) >= dp->numTotalConfigs) {
- return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
- }
- egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(config)].impl];
+ egl_connection_t* const cnx = &gEGLImpl;
if (cnx->dso == 0) {
return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
}
@@ -228,7 +225,7 @@
// EGL.
egl_image_t const * const i = get_image(image);
- return i->images[c->impl];
+ return i->image;
}
// ----------------------------------------------------------------------------
@@ -266,34 +263,17 @@
// get our driver loader
Loader& loader(Loader::getInstance());
- // dynamically load all our EGL implementations
- egl_connection_t* cnx;
-
- cnx = &gEGLImpl[IMPL_SOFTWARE];
+ // dynamically load our EGL implementation
+ egl_connection_t* cnx = &gEGLImpl;
if (cnx->dso == 0) {
- cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_SOFTWARE];
- cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_SOFTWARE];
- cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx);
+ cnx->hooks[egl_connection_t::GLESv1_INDEX] =
+ &gHooks[egl_connection_t::GLESv1_INDEX];
+ cnx->hooks[egl_connection_t::GLESv2_INDEX] =
+ &gHooks[egl_connection_t::GLESv2_INDEX];
+ cnx->dso = loader.open(cnx);
}
- cnx = &gEGLImpl[IMPL_HARDWARE];
- if (cnx->dso == 0) {
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.egl.hw", value, "1");
- if (atoi(value) != 0) {
- cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_HARDWARE];
- cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_HARDWARE];
- cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx);
- } else {
- ALOGD("3D hardware acceleration is disabled");
- }
- }
-
- if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) {
- return EGL_FALSE;
- }
-
- return EGL_TRUE;
+ return cnx->dso ? EGL_TRUE : EGL_FALSE;
}
static pthread_mutex_t sInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 73aab26..bb2783d 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -44,6 +44,7 @@
#include "egl_impl.h"
#include "egl_object.h"
#include "egl_tls.h"
+#include "egldefs.h"
using namespace android;
@@ -88,24 +89,6 @@
// ----------------------------------------------------------------------------
-template<typename T>
-static __attribute__((noinline))
-int binarySearch(T const sortedArray[], int first, int last, T key) {
- while (first <= last) {
- int mid = (first + last) / 2;
- if (sortedArray[mid] < key) {
- first = mid + 1;
- } else if (key < sortedArray[mid]) {
- last = mid - 1;
- } else {
- return mid;
- }
- }
- return -1;
-}
-
-// ----------------------------------------------------------------------------
-
namespace android {
extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
extern EGLBoolean egl_init_drivers();
@@ -183,21 +166,20 @@
egl_display_t const * const dp = validate_display(dpy);
if (!dp) return EGL_FALSE;
- GLint numConfigs = dp->numTotalConfigs;
- if (!configs) {
- *num_config = numConfigs;
- return EGL_TRUE;
+ if (num_config==0) {
+ return setError(EGL_BAD_PARAMETER, EGL_FALSE);
}
- GLint n = 0;
- for (intptr_t i=0 ; i<dp->numTotalConfigs && config_size ; i++) {
- *configs++ = EGLConfig(i);
- config_size--;
- n++;
+ EGLBoolean res = EGL_FALSE;
+ *num_config = 0;
+
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso) {
+ res = cnx->egl.eglGetConfigs(
+ dp->disp.dpy, configs, config_size, num_config);
}
-
- *num_config = n;
- return EGL_TRUE;
+
+ return res;
}
EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
@@ -213,105 +195,13 @@
return setError(EGL_BAD_PARAMETER, EGL_FALSE);
}
- EGLint n;
EGLBoolean res = EGL_FALSE;
*num_config = 0;
-
- // It is unfortunate, but we need to remap the EGL_CONFIG_IDs,
- // to do this, we have to go through the attrib_list array once
- // to figure out both its size and if it contains an EGL_CONFIG_ID
- // key. If so, the full array is copied and patched.
- // NOTE: we assume that there can be only one occurrence
- // of EGL_CONFIG_ID.
-
- EGLint patch_index = -1;
- GLint attr;
- size_t size = 0;
- if (attrib_list) {
- while ((attr=attrib_list[size]) != EGL_NONE) {
- if (attr == EGL_CONFIG_ID)
- patch_index = size;
- size += 2;
- }
- }
- if (patch_index >= 0) {
- size += 2; // we need copy the sentinel as well
- EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint));
- if (new_list == 0)
- return setError(EGL_BAD_ALLOC, EGL_FALSE);
- memcpy(new_list, attrib_list, size*sizeof(EGLint));
-
- // patch the requested EGL_CONFIG_ID
- bool found = false;
- EGLConfig ourConfig(0);
- EGLint& configId(new_list[patch_index+1]);
- for (intptr_t i=0 ; i<dp->numTotalConfigs ; i++) {
- if (dp->configs[i].configId == configId) {
- ourConfig = EGLConfig(i);
- configId = dp->configs[i].implConfigId;
- found = true;
- break;
- }
- }
-
- egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(ourConfig)].impl];
- if (found && cnx->dso) {
- // and switch to the new list
- attrib_list = const_cast<const EGLint *>(new_list);
-
- // At this point, the only configuration that can match is
- // dp->configs[i][index], however, we don't know if it would be
- // rejected because of the other attributes, so we do have to call
- // cnx->egl.eglChooseConfig() -- but we don't have to loop
- // through all the EGLimpl[].
- // We also know we can only get a single config back, and we know
- // which one.
-
- res = cnx->egl.eglChooseConfig(
- dp->disp[ dp->configs[intptr_t(ourConfig)].impl ].dpy,
- attrib_list, configs, config_size, &n);
- if (res && n>0) {
- // n has to be 0 or 1, by construction, and we already know
- // which config it will return (since there can be only one).
- if (configs) {
- configs[0] = ourConfig;
- }
- *num_config = 1;
- }
- }
-
- free(const_cast<EGLint *>(attrib_list));
- return res;
- }
-
-
- for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
- egl_connection_t* const cnx = &gEGLImpl[i];
- if (cnx->dso) {
- if (cnx->egl.eglChooseConfig(
- dp->disp[i].dpy, attrib_list, configs, config_size, &n)) {
- if (configs) {
- // now we need to convert these client EGLConfig to our
- // internal EGLConfig format.
- // This is done in O(n Log(n)) time.
- for (int j=0 ; j<n ; j++) {
- egl_config_t key(i, configs[j]);
- intptr_t index = binarySearch<egl_config_t>(
- dp->configs, 0, dp->numTotalConfigs, key);
- if (index >= 0) {
- configs[j] = EGLConfig(index);
- } else {
- return setError(EGL_BAD_CONFIG, EGL_FALSE);
- }
- }
- configs += n;
- config_size -= n;
- }
- *num_config += n;
- res = EGL_TRUE;
- }
- }
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso) {
+ res = cnx->egl.eglChooseConfig(
+ dp->disp.dpy, attrib_list, configs, config_size, num_config);
}
return res;
}
@@ -325,13 +215,8 @@
egl_connection_t* cnx = validate_display_config(dpy, config, dp);
if (!cnx) return EGL_FALSE;
- if (attribute == EGL_CONFIG_ID) {
- *value = dp->configs[intptr_t(config)].configId;
- return EGL_TRUE;
- }
return cnx->egl.eglGetConfigAttrib(
- dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
- dp->configs[intptr_t(config)].config, attribute, value);
+ dp->disp.dpy, config, attribute, value);
}
// ----------------------------------------------------------------------------
@@ -347,8 +232,7 @@
egl_display_t const* dp = 0;
egl_connection_t* cnx = validate_display_config(dpy, config, dp);
if (cnx) {
- EGLDisplay iDpy = dp->disp[ dp->configs[intptr_t(config)].impl ].dpy;
- EGLConfig iConfig = dp->configs[intptr_t(config)].config;
+ EGLDisplay iDpy = dp->disp.dpy;
EGLint format;
if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) {
@@ -359,7 +243,7 @@
// set the native window's buffers format to match this config
if (cnx->egl.eglGetConfigAttrib(iDpy,
- iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
+ config, EGL_NATIVE_VISUAL_ID, &format)) {
if (format != 0) {
int err = native_window_set_buffers_format(window, format);
if (err != 0) {
@@ -377,10 +261,9 @@
anw->setSwapInterval(anw, 1);
EGLSurface surface = cnx->egl.eglCreateWindowSurface(
- iDpy, iConfig, window, attrib_list);
+ iDpy, config, window, attrib_list);
if (surface != EGL_NO_SURFACE) {
- egl_surface_t* s = new egl_surface_t(dpy, config, window, surface,
- dp->configs[intptr_t(config)].impl, cnx);
+ egl_surface_t* s = new egl_surface_t(dpy, config, window, surface, cnx);
return s;
}
@@ -401,11 +284,9 @@
egl_connection_t* cnx = validate_display_config(dpy, config, dp);
if (cnx) {
EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
- dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
- dp->configs[intptr_t(config)].config, pixmap, attrib_list);
+ dp->disp.dpy, config, pixmap, attrib_list);
if (surface != EGL_NO_SURFACE) {
- egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
- dp->configs[intptr_t(config)].impl, cnx);
+ egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, cnx);
return s;
}
}
@@ -421,11 +302,9 @@
egl_connection_t* cnx = validate_display_config(dpy, config, dp);
if (cnx) {
EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
- dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
- dp->configs[intptr_t(config)].config, attrib_list);
+ dp->disp.dpy, config, attrib_list);
if (surface != EGL_NO_SURFACE) {
- egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface,
- dp->configs[intptr_t(config)].impl, cnx);
+ egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, cnx);
return s;
}
}
@@ -444,8 +323,7 @@
return setError(EGL_BAD_SURFACE, EGL_FALSE);
egl_surface_t * const s = get_surface(surface);
- EGLBoolean result = s->cnx->egl.eglDestroySurface(
- dp->disp[s->impl].dpy, s->surface);
+ EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
if (result == EGL_TRUE) {
_s.terminate();
}
@@ -465,16 +343,8 @@
return setError(EGL_BAD_SURFACE, EGL_FALSE);
egl_surface_t const * const s = get_surface(surface);
- EGLBoolean result(EGL_TRUE);
- if (attribute == EGL_CONFIG_ID) {
- // We need to remap EGL_CONFIG_IDs
- *value = dp->configs[intptr_t(s->config)].configId;
- } else {
- result = s->cnx->egl.eglQuerySurface(
- dp->disp[s->impl].dpy, s->surface, attribute, value);
- }
-
- return result;
+ return s->cnx->egl.eglQuerySurface(
+ dp->disp.dpy, s->surface, attribute, value);
}
void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
@@ -514,9 +384,7 @@
share_list = c->context;
}
EGLContext context = cnx->egl.eglCreateContext(
- dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
- dp->configs[intptr_t(config)].config,
- share_list, attrib_list);
+ dp->disp.dpy, config, share_list, attrib_list);
if (context != EGL_NO_CONTEXT) {
// figure out if it's a GLESv1 or GLESv2
int version = 0;
@@ -526,15 +394,14 @@
GLint value = *attrib_list++;
if (attr == EGL_CONTEXT_CLIENT_VERSION) {
if (value == 1) {
- version = GLESv1_INDEX;
+ version = egl_connection_t::GLESv1_INDEX;
} else if (value == 2) {
- version = GLESv2_INDEX;
+ version = egl_connection_t::GLESv2_INDEX;
}
}
};
}
- egl_context_t* c = new egl_context_t(dpy, context, config,
- dp->configs[intptr_t(config)].impl, cnx, version);
+ egl_context_t* c = new egl_context_t(dpy, context, config, cnx, version);
#if EGL_TRACE
if (gEGLDebugLevel > 0)
GLTrace_eglCreateContext(version, c);
@@ -558,8 +425,7 @@
return setError(EGL_BAD_CONTEXT, EGL_FALSE);
egl_context_t * const c = get_context(ctx);
- EGLBoolean result = c->cnx->egl.eglDestroyContext(
- dp->disp[c->impl].dpy, c->context);
+ EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
if (result == EGL_TRUE) {
_c.terminate();
}
@@ -625,20 +491,12 @@
// retrieve the underlying implementation's draw EGLSurface
if (draw != EGL_NO_SURFACE) {
d = get_surface(draw);
- // make sure the EGLContext and EGLSurface passed in are for
- // the same driver
- if (c && d->impl != c->impl)
- return setError(EGL_BAD_MATCH, EGL_FALSE);
impl_draw = d->surface;
}
// retrieve the underlying implementation's read EGLSurface
if (read != EGL_NO_SURFACE) {
r = get_surface(read);
- // make sure the EGLContext and EGLSurface passed in are for
- // the same driver
- if (c && r->impl != c->impl)
- return setError(EGL_BAD_MATCH, EGL_FALSE);
impl_read = r->surface;
}
@@ -682,17 +540,9 @@
if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
egl_context_t * const c = get_context(ctx);
+ return c->cnx->egl.eglQueryContext(
+ dp->disp.dpy, c->context, attribute, value);
- EGLBoolean result(EGL_TRUE);
- if (attribute == EGL_CONFIG_ID) {
- *value = dp->configs[intptr_t(c->config)].configId;
- } else {
- // We need to remap EGL_CONFIG_IDs
- result = c->cnx->egl.eglQueryContext(
- dp->disp[c->impl].dpy, c->context, attribute, value);
- }
-
- return result;
}
EGLContext eglGetCurrentContext(void)
@@ -744,64 +594,37 @@
EGLBoolean eglWaitGL(void)
{
- // could be called before eglInitialize(), but we wouldn't have a context
- // then, and this function would return GL_TRUE, which isn't wrong.
-
clearError();
- EGLBoolean res = EGL_TRUE;
- EGLContext ctx = getContext();
- if (ctx) {
- egl_context_t const * const c = get_context(ctx);
- if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
- if (uint32_t(c->impl)>=2)
- return setError(EGL_BAD_CONTEXT, EGL_FALSE);
- egl_connection_t* const cnx = &gEGLImpl[c->impl];
- if (!cnx->dso)
- return setError(EGL_BAD_CONTEXT, EGL_FALSE);
- res = cnx->egl.eglWaitGL();
- }
- return res;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (!cnx->dso)
+ return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+
+ return cnx->egl.eglWaitGL();
}
EGLBoolean eglWaitNative(EGLint engine)
{
- // could be called before eglInitialize(), but we wouldn't have a context
- // then, and this function would return GL_TRUE, which isn't wrong.
-
clearError();
- EGLBoolean res = EGL_TRUE;
- EGLContext ctx = getContext();
- if (ctx) {
- egl_context_t const * const c = get_context(ctx);
- if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
- if (uint32_t(c->impl)>=2)
- return setError(EGL_BAD_CONTEXT, EGL_FALSE);
- egl_connection_t* const cnx = &gEGLImpl[c->impl];
- if (!cnx->dso)
- return setError(EGL_BAD_CONTEXT, EGL_FALSE);
- res = cnx->egl.eglWaitNative(engine);
- }
- return res;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (!cnx->dso)
+ return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+
+ return cnx->egl.eglWaitNative(engine);
}
EGLint eglGetError(void)
{
- EGLint result = EGL_SUCCESS;
- EGLint err;
- for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
- err = EGL_SUCCESS;
- egl_connection_t* const cnx = &gEGLImpl[i];
- if (cnx->dso)
- err = cnx->egl.eglGetError();
- if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
- result = err;
+ EGLint err = EGL_SUCCESS;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso) {
+ err = cnx->egl.eglGetError();
}
- err = egl_tls_t::getError();
- if (result == EGL_SUCCESS)
- result = err;
- return result;
+ if (err == EGL_SUCCESS) {
+ err = egl_tls_t::getError();
+ }
+ return err;
}
// Note: Similar implementations of these functions also exist in
@@ -885,20 +708,20 @@
if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
bool found = false;
- for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
- egl_connection_t* const cnx = &gEGLImpl[i];
- if (cnx->dso && cnx->egl.eglGetProcAddress) {
- found = true;
- // Extensions are independent of the bound context
- cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
- cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
+
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglGetProcAddress) {
+ found = true;
+ // Extensions are independent of the bound context
+ cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
+ cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
#if EGL_TRACE
- debugHooks->ext.extensions[slot] =
- gHooksTrace.ext.extensions[slot] =
+ debugHooks->ext.extensions[slot] =
+ gHooksTrace.ext.extensions[slot] =
#endif
- cnx->egl.eglGetProcAddress(procname);
- }
+ cnx->egl.eglGetProcAddress(procname);
}
+
if (found) {
addr = gExtensionForwarders[slot];
@@ -937,7 +760,7 @@
#endif
egl_surface_t const * const s = get_surface(draw);
- return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface);
+ return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
}
EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
@@ -953,8 +776,7 @@
return setError(EGL_BAD_SURFACE, EGL_FALSE);
egl_surface_t const * const s = get_surface(surface);
- return s->cnx->egl.eglCopyBuffers(
- dp->disp[s->impl].dpy, s->surface, target);
+ return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
}
const char* eglQueryString(EGLDisplay dpy, EGLint name)
@@ -973,12 +795,8 @@
return dp->getExtensionString();
case EGL_CLIENT_APIS:
return dp->getClientApiString();
- case EGL_VERSION_HW_ANDROID: {
- if (gEGLImpl[IMPL_HARDWARE].dso) {
- return dp->disp[IMPL_HARDWARE].queryString.version;
- }
- return dp->disp[IMPL_SOFTWARE].queryString.version;
- }
+ case EGL_VERSION_HW_ANDROID:
+ return dp->disp.queryString.version;
}
return setError(EGL_BAD_PARAMETER, (const char *)0);
}
@@ -1003,7 +821,7 @@
egl_surface_t const * const s = get_surface(surface);
if (s->cnx->egl.eglSurfaceAttrib) {
return s->cnx->egl.eglSurfaceAttrib(
- dp->disp[s->impl].dpy, s->surface, attribute, value);
+ dp->disp.dpy, s->surface, attribute, value);
}
return setError(EGL_BAD_SURFACE, EGL_FALSE);
}
@@ -1023,7 +841,7 @@
egl_surface_t const * const s = get_surface(surface);
if (s->cnx->egl.eglBindTexImage) {
return s->cnx->egl.eglBindTexImage(
- dp->disp[s->impl].dpy, s->surface, buffer);
+ dp->disp.dpy, s->surface, buffer);
}
return setError(EGL_BAD_SURFACE, EGL_FALSE);
}
@@ -1043,7 +861,7 @@
egl_surface_t const * const s = get_surface(surface);
if (s->cnx->egl.eglReleaseTexImage) {
return s->cnx->egl.eglReleaseTexImage(
- dp->disp[s->impl].dpy, s->surface, buffer);
+ dp->disp.dpy, s->surface, buffer);
}
return setError(EGL_BAD_SURFACE, EGL_FALSE);
}
@@ -1056,17 +874,11 @@
if (!dp) return EGL_FALSE;
EGLBoolean res = EGL_TRUE;
- for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
- egl_connection_t* const cnx = &gEGLImpl[i];
- if (cnx->dso) {
- if (cnx->egl.eglSwapInterval) {
- if (cnx->egl.eglSwapInterval(
- dp->disp[i].dpy, interval) == EGL_FALSE) {
- res = EGL_FALSE;
- }
- }
- }
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglSwapInterval) {
+ res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
}
+
return res;
}
@@ -1079,23 +891,15 @@
{
clearError();
- // could be called before eglInitialize(), but we wouldn't have a context
- // then, and this function would return GL_TRUE, which isn't wrong.
- EGLBoolean res = EGL_TRUE;
- EGLContext ctx = getContext();
- if (ctx) {
- egl_context_t const * const c = get_context(ctx);
- if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
- if (uint32_t(c->impl)>=2)
- return setError(EGL_BAD_CONTEXT, EGL_FALSE);
- egl_connection_t* const cnx = &gEGLImpl[c->impl];
- if (!cnx->dso)
- return setError(EGL_BAD_CONTEXT, EGL_FALSE);
- if (cnx->egl.eglWaitClient) {
- res = cnx->egl.eglWaitClient();
- } else {
- res = cnx->egl.eglWaitGL();
- }
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (!cnx->dso)
+ return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+
+ EGLBoolean res;
+ if (cnx->egl.eglWaitClient) {
+ res = cnx->egl.eglWaitClient();
+ } else {
+ res = cnx->egl.eglWaitGL();
}
return res;
}
@@ -1110,15 +914,9 @@
// bind this API on all EGLs
EGLBoolean res = EGL_TRUE;
- for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
- egl_connection_t* const cnx = &gEGLImpl[i];
- if (cnx->dso) {
- if (cnx->egl.eglBindAPI) {
- if (cnx->egl.eglBindAPI(api) == EGL_FALSE) {
- res = EGL_FALSE;
- }
- }
- }
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglBindAPI) {
+ res = cnx->egl.eglBindAPI(api);
}
return res;
}
@@ -1131,16 +929,11 @@
return setError(EGL_BAD_PARAMETER, EGL_FALSE);
}
- for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
- egl_connection_t* const cnx = &gEGLImpl[i];
- if (cnx->dso) {
- if (cnx->egl.eglQueryAPI) {
- // the first one we find is okay, because they all
- // should be the same
- return cnx->egl.eglQueryAPI();
- }
- }
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglQueryAPI) {
+ return cnx->egl.eglQueryAPI();
}
+
// or, it can only be OpenGL ES
return EGL_OPENGL_ES_API;
}
@@ -1152,14 +945,11 @@
// If there is context bound to the thread, release it
egl_display_t::loseCurrent(get_context(getContext()));
- for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
- egl_connection_t* const cnx = &gEGLImpl[i];
- if (cnx->dso) {
- if (cnx->egl.eglReleaseThread) {
- cnx->egl.eglReleaseThread();
- }
- }
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglReleaseThread) {
+ cnx->egl.eglReleaseThread();
}
+
egl_tls_t::clearTLS();
#if EGL_TRACE
if (gEGLDebugLevel > 0)
@@ -1179,9 +969,7 @@
if (!cnx) return EGL_FALSE;
if (cnx->egl.eglCreatePbufferFromClientBuffer) {
return cnx->egl.eglCreatePbufferFromClientBuffer(
- dp->disp[ dp->configs[intptr_t(config)].impl ].dpy,
- buftype, buffer,
- dp->configs[intptr_t(config)].config, attrib_list);
+ dp->disp.dpy, buftype, buffer, config, attrib_list);
}
return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
}
@@ -1205,7 +993,7 @@
egl_surface_t const * const s = get_surface(surface);
if (s->cnx->egl.eglLockSurfaceKHR) {
return s->cnx->egl.eglLockSurfaceKHR(
- dp->disp[s->impl].dpy, s->surface, attrib_list);
+ dp->disp.dpy, s->surface, attrib_list);
}
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
}
@@ -1223,8 +1011,7 @@
egl_surface_t const * const s = get_surface(surface);
if (s->cnx->egl.eglUnlockSurfaceKHR) {
- return s->cnx->egl.eglUnlockSurfaceKHR(
- dp->disp[s->impl].dpy, s->surface);
+ return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
}
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
}
@@ -1244,12 +1031,12 @@
egl_context_t * const c = get_context(ctx);
// since we have an EGLContext, we know which implementation to use
EGLImageKHR image = c->cnx->egl.eglCreateImageKHR(
- dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list);
+ dp->disp.dpy, c->context, target, buffer, attrib_list);
if (image == EGL_NO_IMAGE_KHR)
return image;
egl_image_t* result = new egl_image_t(dpy, ctx);
- result->images[c->impl] = image;
+ result->image = image;
return (EGLImageKHR)result;
} else {
// EGL_NO_CONTEXT is a valid parameter
@@ -1261,23 +1048,14 @@
EGLint currentError = eglGetError();
- EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS];
- bool success = false;
- for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
- egl_connection_t* const cnx = &gEGLImpl[i];
- implImages[i] = EGL_NO_IMAGE_KHR;
- if (cnx->dso) {
- if (cnx->egl.eglCreateImageKHR) {
- implImages[i] = cnx->egl.eglCreateImageKHR(
- dp->disp[i].dpy, ctx, target, buffer, attrib_list);
- if (implImages[i] != EGL_NO_IMAGE_KHR) {
- success = true;
- }
- }
- }
+ EGLImageKHR implImage = EGL_NO_IMAGE_KHR;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglCreateImageKHR) {
+ implImage = cnx->egl.eglCreateImageKHR(
+ dp->disp.dpy, ctx, target, buffer, attrib_list);
}
- if (!success) {
+ if (implImage == EGL_NO_IMAGE_KHR) {
// failure, if there was an error when we entered this function,
// the error flag must not be updated.
// Otherwise, the error is whatever happened in the implementation
@@ -1289,13 +1067,12 @@
} else {
// In case of success, we need to clear all error flags
// (especially those caused by the implementation that didn't
- // succeed). TODO: we could avoid this if we knew this was
- // a "full" success (all implementation succeeded).
+ // succeed).
eglGetError();
}
egl_image_t* result = new egl_image_t(dpy, ctx);
- memcpy(result->images, implImages, sizeof(implImages));
+ result->image = implImage;
return (EGLImageKHR)result;
}
}
@@ -1312,19 +1089,17 @@
egl_image_t* image = get_image(img);
bool success = false;
- for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
- egl_connection_t* const cnx = &gEGLImpl[i];
- if (image->images[i] != EGL_NO_IMAGE_KHR) {
- if (cnx->dso) {
- if (cnx->egl.eglDestroyImageKHR) {
- if (cnx->egl.eglDestroyImageKHR(
- dp->disp[i].dpy, image->images[i])) {
- success = true;
- }
- }
+
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (image->image != EGL_NO_IMAGE_KHR) {
+ if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
+ if (cnx->egl.eglDestroyImageKHR(
+ dp->disp.dpy, image->image)) {
+ success = true;
}
}
}
+
if (!success)
return EGL_FALSE;
@@ -1354,7 +1129,7 @@
EGLSyncKHR result = EGL_NO_SYNC_KHR;
if (c->cnx->egl.eglCreateSyncKHR) {
EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
- dp->disp[c->impl].dpy, type, attrib_list);
+ dp->disp.dpy, type, attrib_list);
if (sync == EGL_NO_SYNC_KHR)
return sync;
result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
@@ -1382,7 +1157,7 @@
egl_context_t * const c = get_context(ctx);
if (c->cnx->egl.eglDestroySyncKHR) {
result = c->cnx->egl.eglDestroySyncKHR(
- dp->disp[c->impl].dpy, syncObject->sync);
+ dp->disp.dpy, syncObject->sync);
if (result)
_s.terminate();
}
@@ -1408,7 +1183,7 @@
egl_context_t * const c = get_context(ctx);
if (c->cnx->egl.eglClientWaitSyncKHR) {
return c->cnx->egl.eglClientWaitSyncKHR(
- dp->disp[c->impl].dpy, syncObject->sync, flags, timeout);
+ dp->disp.dpy, syncObject->sync, flags, timeout);
}
return EGL_FALSE;
@@ -1434,7 +1209,7 @@
egl_context_t * const c = get_context(ctx);
if (c->cnx->egl.eglGetSyncAttribKHR) {
return c->cnx->egl.eglGetSyncAttribKHR(
- dp->disp[c->impl].dpy, syncObject->sync, attribute, value);
+ dp->disp.dpy, syncObject->sync, attribute, value);
}
return EGL_FALSE;
@@ -1458,12 +1233,10 @@
}
EGLuint64NV ret = 0;
- egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE];
+ egl_connection_t* const cnx = &gEGLImpl;
- if (cnx->dso) {
- if (cnx->egl.eglGetSystemTimeFrequencyNV) {
- return cnx->egl.eglGetSystemTimeFrequencyNV();
- }
+ if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
+ return cnx->egl.eglGetSystemTimeFrequencyNV();
}
return setErrorQuiet(EGL_BAD_DISPLAY, 0);
@@ -1478,12 +1251,10 @@
}
EGLuint64NV ret = 0;
- egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE];
+ egl_connection_t* const cnx = &gEGLImpl;
- if (cnx->dso) {
- if (cnx->egl.eglGetSystemTimeNV) {
- return cnx->egl.eglGetSystemTimeNV();
- }
+ if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
+ return cnx->egl.eglGetSystemTimeNV();
}
return setErrorQuiet(EGL_BAD_DISPLAY, 0);
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index 7fd6519..c79fb5f 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -83,39 +83,39 @@
void egl_cache_t::initialize(egl_display_t *display) {
Mutex::Autolock lock(mMutex);
- for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
- egl_connection_t* const cnx = &gEGLImpl[i];
- if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
- const char* exts = display->disp[i].queryString.extensions;
- size_t bcExtLen = strlen(BC_EXT_STR);
- size_t extsLen = strlen(exts);
- bool equal = !strcmp(BC_EXT_STR, exts);
- bool atStart = !strncmp(BC_EXT_STR " ", exts, bcExtLen+1);
- bool atEnd = (bcExtLen+1) < extsLen &&
- !strcmp(" " BC_EXT_STR, exts + extsLen - (bcExtLen+1));
- bool inMiddle = strstr(exts, " " BC_EXT_STR " ");
- if (equal || atStart || atEnd || inMiddle) {
- PFNEGLSETBLOBCACHEFUNCSANDROIDPROC eglSetBlobCacheFuncsANDROID;
- eglSetBlobCacheFuncsANDROID =
- reinterpret_cast<PFNEGLSETBLOBCACHEFUNCSANDROIDPROC>(
+
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
+ const char* exts = display->disp.queryString.extensions;
+ size_t bcExtLen = strlen(BC_EXT_STR);
+ size_t extsLen = strlen(exts);
+ bool equal = !strcmp(BC_EXT_STR, exts);
+ bool atStart = !strncmp(BC_EXT_STR " ", exts, bcExtLen+1);
+ bool atEnd = (bcExtLen+1) < extsLen &&
+ !strcmp(" " BC_EXT_STR, exts + extsLen - (bcExtLen+1));
+ bool inMiddle = strstr(exts, " " BC_EXT_STR " ");
+ if (equal || atStart || atEnd || inMiddle) {
+ PFNEGLSETBLOBCACHEFUNCSANDROIDPROC eglSetBlobCacheFuncsANDROID;
+ eglSetBlobCacheFuncsANDROID =
+ reinterpret_cast<PFNEGLSETBLOBCACHEFUNCSANDROIDPROC>(
cnx->egl.eglGetProcAddress(
"eglSetBlobCacheFuncsANDROID"));
- if (eglSetBlobCacheFuncsANDROID == NULL) {
- ALOGE("EGL_ANDROID_blob_cache advertised by display %d, "
- "but unable to get eglSetBlobCacheFuncsANDROID", i);
- continue;
- }
+ if (eglSetBlobCacheFuncsANDROID == NULL) {
+ ALOGE("EGL_ANDROID_blob_cache advertised, "
+ "but unable to get eglSetBlobCacheFuncsANDROID");
+ return;
+ }
- eglSetBlobCacheFuncsANDROID(display->disp[i].dpy,
- android::setBlob, android::getBlob);
- EGLint err = cnx->egl.eglGetError();
- if (err != EGL_SUCCESS) {
- ALOGE("eglSetBlobCacheFuncsANDROID resulted in an error: "
- "%#x", err);
- }
+ eglSetBlobCacheFuncsANDROID(display->disp.dpy,
+ android::setBlob, android::getBlob);
+ EGLint err = cnx->egl.eglGetError();
+ if (err != EGL_SUCCESS) {
+ ALOGE("eglSetBlobCacheFuncsANDROID resulted in an error: "
+ "%#x", err);
}
}
}
+
mInitialized = true;
}
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 6b2ae51..c85b4ce 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -60,18 +60,12 @@
extern void initEglTraceLevel();
extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
-static int cmp_configs(const void* a, const void *b) {
- const egl_config_t& c0 = *(egl_config_t const *)a;
- const egl_config_t& c1 = *(egl_config_t const *)b;
- return c0<c1 ? -1 : (c1<c0 ? 1 : 0);
-}
-
// ----------------------------------------------------------------------------
egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS];
egl_display_t::egl_display_t() :
- magic('_dpy'), numTotalConfigs(0), configs(0), refs(0) {
+ magic('_dpy'), refs(0) {
}
egl_display_t::~egl_display_t() {
@@ -119,15 +113,13 @@
// get our driver loader
Loader& loader(Loader::getInstance());
- for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
- egl_connection_t* const cnx = &gEGLImpl[i];
- if (cnx->dso && disp[i].dpy == EGL_NO_DISPLAY) {
- EGLDisplay dpy = cnx->egl.eglGetDisplay(display);
- disp[i].dpy = dpy;
- if (dpy == EGL_NO_DISPLAY) {
- loader.close(cnx->dso);
- cnx->dso = NULL;
- }
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && disp.dpy == EGL_NO_DISPLAY) {
+ EGLDisplay dpy = cnx->egl.eglGetDisplay(display);
+ disp.dpy = dpy;
+ if (dpy == EGL_NO_DISPLAY) {
+ loader.close(cnx->dso);
+ cnx->dso = NULL;
}
}
@@ -160,12 +152,11 @@
// initialize each EGL and
// build our own extension string first, based on the extension we know
// and the extension supported by our client implementation
- for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
- egl_connection_t* const cnx = &gEGLImpl[i];
- cnx->major = -1;
- cnx->minor = -1;
- if (!cnx->dso)
- continue;
+
+ egl_connection_t* const cnx = &gEGLImpl;
+ cnx->major = -1;
+ cnx->minor = -1;
+ if (cnx->dso) {
#if defined(ADRENO130)
#warning "Adreno-130 eglInitialize() workaround"
@@ -177,31 +168,30 @@
* eglGetDisplay() before calling eglInitialize();
*/
if (i == IMPL_HARDWARE) {
- disp[i].dpy =
- cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ disp[i].dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
}
#endif
- EGLDisplay idpy = disp[i].dpy;
+ EGLDisplay idpy = disp.dpy;
if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
- //ALOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
- // i, idpy, cnx->major, cnx->minor, cnx);
+ //ALOGD("initialized dpy=%p, ver=%d.%d, cnx=%p",
+ // idpy, cnx->major, cnx->minor, cnx);
// display is now initialized
- disp[i].state = egl_display_t::INITIALIZED;
+ disp.state = egl_display_t::INITIALIZED;
// get the query-strings for this display for each implementation
- disp[i].queryString.vendor = cnx->egl.eglQueryString(idpy,
+ disp.queryString.vendor = cnx->egl.eglQueryString(idpy,
EGL_VENDOR);
- disp[i].queryString.version = cnx->egl.eglQueryString(idpy,
+ disp.queryString.version = cnx->egl.eglQueryString(idpy,
EGL_VERSION);
- disp[i].queryString.extensions = cnx->egl.eglQueryString(idpy,
+ disp.queryString.extensions = cnx->egl.eglQueryString(idpy,
EGL_EXTENSIONS);
- disp[i].queryString.clientApi = cnx->egl.eglQueryString(idpy,
+ disp.queryString.clientApi = cnx->egl.eglQueryString(idpy,
EGL_CLIENT_APIS);
} else {
- ALOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
+ ALOGW("eglInitialize(%p) failed (%s)", idpy,
egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
}
}
@@ -211,7 +201,7 @@
mVersionString.setTo(sVersionString);
mClientApiString.setTo(sClientApiString);
- // we only add extensions that exist in at least one implementation
+ // we only add extensions that exist in the implementation
char const* start = sExtensionString;
char const* end;
do {
@@ -223,15 +213,13 @@
if (len) {
// NOTE: we could avoid the copy if we had strnstr.
const String8 ext(start, len);
- // now go through all implementations and look for this extension
- for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
- if (disp[i].queryString.extensions) {
- // if we find it, add this extension string to our list
- // (and don't forget the space)
- const char* match = strstr(disp[i].queryString.extensions, ext.string());
- if (match && (match[len] == ' ' || match[len] == 0)) {
- mExtensionString.append(start, len+1);
- }
+ // now look for this extension
+ if (disp.queryString.extensions) {
+ // if we find it, add this extension string to our list
+ // (and don't forget the space)
+ const char* match = strstr(disp.queryString.extensions, ext.string());
+ if (match && (match[len] == ' ' || match[len] == 0)) {
+ mExtensionString.append(start, len+1);
}
}
}
@@ -242,52 +230,12 @@
egl_cache_t::get()->initialize(this);
- EGLBoolean res = EGL_FALSE;
- for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
- egl_connection_t* const cnx = &gEGLImpl[i];
- if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
- EGLint n;
- if (cnx->egl.eglGetConfigs(disp[i].dpy, 0, 0, &n)) {
- disp[i].config = (EGLConfig*) malloc(sizeof(EGLConfig) * n);
- if (disp[i].config) {
- if (cnx->egl.eglGetConfigs(disp[i].dpy, disp[i].config, n,
- &disp[i].numConfigs)) {
- numTotalConfigs += n;
- res = EGL_TRUE;
- }
- }
- }
- }
- }
-
- if (res == EGL_TRUE) {
- configs = new egl_config_t[numTotalConfigs];
- for (int i = 0, k = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
- egl_connection_t* const cnx = &gEGLImpl[i];
- if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
- for (int j = 0; j < disp[i].numConfigs; j++) {
- configs[k].impl = i;
- configs[k].config = disp[i].config[j];
- configs[k].configId = k + 1; // CONFIG_ID start at 1
- // store the implementation's CONFIG_ID
- cnx->egl.eglGetConfigAttrib(disp[i].dpy, disp[i].config[j],
- EGL_CONFIG_ID, &configs[k].implConfigId);
- k++;
- }
- }
- }
-
- // sort our configurations so we can do binary-searches
- qsort(configs, numTotalConfigs, sizeof(egl_config_t), cmp_configs);
-
- refs++;
- if (major != NULL)
- *major = VERSION_MAJOR;
- if (minor != NULL)
- *minor = VERSION_MINOR;
- return EGL_TRUE;
- }
- return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
+ refs++;
+ if (major != NULL)
+ *major = VERSION_MAJOR;
+ if (minor != NULL)
+ *minor = VERSION_MINOR;
+ return EGL_TRUE;
}
EGLBoolean egl_display_t::terminate() {
@@ -305,22 +253,15 @@
}
EGLBoolean res = EGL_FALSE;
- for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
- egl_connection_t* const cnx = &gEGLImpl[i];
- if (cnx->dso && disp[i].state == egl_display_t::INITIALIZED) {
- if (cnx->egl.eglTerminate(disp[i].dpy) == EGL_FALSE) {
- ALOGW("%d: eglTerminate(%p) failed (%s)", i, disp[i].dpy,
- egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
- }
- // REVISIT: it's unclear what to do if eglTerminate() fails
- free(disp[i].config);
-
- disp[i].numConfigs = 0;
- disp[i].config = 0;
- disp[i].state = egl_display_t::TERMINATED;
-
- res = EGL_TRUE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && disp.state == egl_display_t::INITIALIZED) {
+ if (cnx->egl.eglTerminate(disp.dpy) == EGL_FALSE) {
+ ALOGW("eglTerminate(%p) failed (%s)", disp.dpy,
+ egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
}
+ // REVISIT: it's unclear what to do if eglTerminate() fails
+ disp.state = egl_display_t::TERMINATED;
+ res = EGL_TRUE;
}
// Mark all objects remaining in the list as terminated, unless
@@ -337,8 +278,6 @@
objects.clear();
refs--;
- numTotalConfigs = 0;
- delete[] configs;
return res;
}
@@ -390,13 +329,13 @@
Mutex::Autolock _l(lock);
if (c) {
result = c->cnx->egl.eglMakeCurrent(
- disp[c->impl].dpy, impl_draw, impl_read, impl_ctx);
+ disp.dpy, impl_draw, impl_read, impl_ctx);
if (result == EGL_TRUE) {
c->onMakeCurrent(draw, read);
}
} else {
result = cur_c->cnx->egl.eglMakeCurrent(
- disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx);
+ disp.dpy, impl_draw, impl_read, impl_ctx);
if (result == EGL_TRUE) {
cur_c->onLooseCurrent();
}
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index f3c4ddf..6348228 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -44,23 +44,6 @@
// ----------------------------------------------------------------------------
-struct egl_config_t {
- egl_config_t() {}
- egl_config_t(int impl, EGLConfig config)
- : impl(impl), config(config), configId(0), implConfigId(0) { }
- int impl; // the implementation this config is for
- EGLConfig config; // the implementation's EGLConfig
- EGLint configId; // our CONFIG_ID
- EGLint implConfigId; // the implementation's CONFIG_ID
- inline bool operator < (const egl_config_t& rhs) const {
- if (impl < rhs.impl) return true;
- if (impl > rhs.impl) return false;
- return config < rhs.config;
- }
-};
-
-// ----------------------------------------------------------------------------
-
class EGLAPI egl_display_t { // marked as EGLAPI for testing purposes
static egl_display_t sDisplay[NUM_DISPLAYS];
EGLDisplay getDisplay(EGLNativeDisplayType display);
@@ -113,12 +96,9 @@
};
struct DisplayImpl {
- DisplayImpl() : dpy(EGL_NO_DISPLAY), config(0),
- state(NOT_INITIALIZED), numConfigs(0) { }
+ DisplayImpl() : dpy(EGL_NO_DISPLAY), state(NOT_INITIALIZED) { }
EGLDisplay dpy;
- EGLConfig* config;
EGLint state;
- EGLint numConfigs;
strings_t queryString;
};
@@ -126,9 +106,7 @@
uint32_t magic;
public:
- DisplayImpl disp[IMPL_NUM_IMPLEMENTATIONS];
- EGLint numTotalConfigs;
- egl_config_t* configs;
+ DisplayImpl disp;
private:
uint32_t refs;
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index b660c53..d0cbb31 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -64,9 +64,9 @@
// ----------------------------------------------------------------------------
egl_context_t::egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
- int impl, egl_connection_t const* cnx, int version) :
+ egl_connection_t const* cnx, int version) :
egl_object_t(get_display(dpy)), dpy(dpy), context(context),
- config(config), read(0), draw(0), impl(impl), cnx(cnx),
+ config(config), read(0), draw(0), cnx(cnx),
version(version)
{
}
@@ -87,7 +87,7 @@
if (gl_extensions.isEmpty()) {
// call the implementation's glGetString(GL_EXTENSIONS)
- const char* exts = (const char *)gEGLImpl[impl].hooks[version]->gl.glGetString(GL_EXTENSIONS);
+ const char* exts = (const char *)gEGLImpl.hooks[version]->gl.glGetString(GL_EXTENSIONS);
gl_extensions.setTo(exts);
if (gl_extensions.find("GL_EXT_debug_marker") < 0) {
String8 temp("GL_EXT_debug_marker ");
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index abd4cbb..f137bad 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -125,7 +125,7 @@
// ----------------------------------------------------------------------------
-class egl_surface_t: public egl_object_t {
+class egl_surface_t : public egl_object_t {
protected:
~egl_surface_t() {
ANativeWindow* const window = win.get();
@@ -140,15 +140,14 @@
typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win,
- EGLSurface surface, int impl, egl_connection_t const* cnx) :
+ EGLSurface surface, egl_connection_t const* cnx) :
egl_object_t(get_display(dpy)), dpy(dpy), surface(surface),
- config(config), win(win), impl(impl), cnx(cnx) {
+ config(config), win(win), cnx(cnx) {
}
EGLDisplay dpy;
EGLSurface surface;
EGLConfig config;
sp<ANativeWindow> win;
- int impl;
egl_connection_t const* cnx;
};
@@ -159,7 +158,7 @@
typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;
egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
- int impl, egl_connection_t const* cnx, int version);
+ egl_connection_t const* cnx, int version);
void onLooseCurrent();
void onMakeCurrent(EGLSurface draw, EGLSurface read);
@@ -169,7 +168,6 @@
EGLConfig config;
EGLSurface read;
EGLSurface draw;
- int impl;
egl_connection_t const* cnx;
int version;
String8 gl_extensions;
@@ -182,12 +180,11 @@
typedef egl_object_t::LocalRef<egl_image_t, EGLImageKHR> Ref;
egl_image_t(EGLDisplay dpy, EGLContext context) :
- egl_object_t(get_display(dpy)), dpy(dpy), context(context) {
- memset(images, 0, sizeof(images));
- }
+ egl_object_t(get_display(dpy)),
+ dpy(dpy), context(context), image(EGL_NO_IMAGE_KHR) { }
EGLDisplay dpy;
EGLContext context;
- EGLImageKHR images[IMPL_NUM_IMPLEMENTATIONS];
+ EGLImageKHR image;
};
class egl_sync_t: public egl_object_t {
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index ff20957..c900c1c 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -19,31 +19,24 @@
#include "hooks.h"
+#define VERSION_MAJOR 1
+#define VERSION_MINOR 4
+
// ----------------------------------------------------------------------------
namespace android {
// ----------------------------------------------------------------------------
-#define VERSION_MAJOR 1
-#define VERSION_MINOR 4
-
// EGLDisplay are global, not attached to a given thread
const unsigned int NUM_DISPLAYS = 1;
-enum {
- IMPL_HARDWARE = 0,
- IMPL_SOFTWARE,
- IMPL_NUM_IMPLEMENTATIONS
-};
-
-enum {
- GLESv1_INDEX = 0,
- GLESv2_INDEX = 1,
-};
-
// ----------------------------------------------------------------------------
-struct egl_connection_t
-{
+struct egl_connection_t {
+ enum {
+ GLESv1_INDEX = 0,
+ GLESv2_INDEX = 1
+ };
+
inline egl_connection_t() : dso(0) { }
void * dso;
gl_hooks_t * hooks[2];
@@ -54,7 +47,7 @@
// ----------------------------------------------------------------------------
-extern gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
+extern gl_hooks_t gHooks[2];
extern gl_hooks_t gHooksNoContext;
extern pthread_key_t gGLWrapperKey;
extern "C" void gl_unimplemented();
@@ -63,7 +56,7 @@
extern char const * const gl_names[];
extern char const * const egl_names[];
-extern egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS];
+extern egl_connection_t gEGLImpl;
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
index 871b5dc..3e185bc 100644
--- a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
@@ -15,9 +15,13 @@
*/
#include <cutils/log.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
#include "gltrace.pb.h"
+#include "gltrace_api.h"
#include "gltrace_context.h"
#include "gltrace_fixup.h"
@@ -198,6 +202,20 @@
arg_strpp->add_charvalue(src);
}
+void fixup_glUniformGenericInteger(int argIndex, int nIntegers, GLMessage *glmsg) {
+ /* void glUniform?iv(GLint location, GLsizei count, const GLint *value); */
+ GLMessage_DataType *arg_values = glmsg->mutable_args(argIndex);
+ GLint *src = (GLint*)arg_values->intvalue(0);
+
+ arg_values->set_type(GLMessage::DataType::INT);
+ arg_values->set_isarray(true);
+ arg_values->clear_intvalue();
+
+ for (int i = 0; i < nIntegers; i++) {
+ arg_values->add_intvalue(*src++);
+ }
+}
+
void fixup_glUniformGeneric(int argIndex, int nFloats, GLMessage *glmsg) {
GLMessage_DataType *arg_values = glmsg->mutable_args(argIndex);
GLfloat *src = (GLfloat*)arg_values->intvalue(0);
@@ -223,6 +241,10 @@
GLMessage_DataType *arg_intarray = glmsg->mutable_args(argIndex);
GLint *intp = (GLint *)arg_intarray->intvalue(0);
+ if (intp == NULL) {
+ return;
+ }
+
arg_intarray->set_type(GLMessage::DataType::INT);
arg_intarray->set_isarray(true);
arg_intarray->clear_intvalue();
@@ -232,6 +254,15 @@
}
}
+void fixup_GenericEnumArray(int argIndex, int nEnums, GLMessage *glmsg) {
+ // fixup as if they were ints
+ fixup_GenericIntArray(argIndex, nEnums, glmsg);
+
+ // and then set the data type to be enum
+ GLMessage_DataType *arg_enumarray = glmsg->mutable_args(argIndex);
+ arg_enumarray->set_type(GLMessage::DataType::ENUM);
+}
+
void fixup_glGenGeneric(GLMessage *glmsg) {
/* void glGen*(GLsizei n, GLuint * buffers); */
GLMessage_DataType arg_n = glmsg->args(0);
@@ -270,6 +301,84 @@
arg_params->add_floatvalue(*src);
}
+void fixup_glLinkProgram(GLMessage *glmsg) {
+ /* void glLinkProgram(GLuint program); */
+ GLuint program = glmsg->args(0).intvalue(0);
+
+ /* We don't have to fixup this call, but as soon as a program is linked,
+ we obtain information about all active attributes and uniforms to
+ pass on to the debugger. Note that in order to pass this info to
+ the debugger, all we need to do is call the trace versions of the
+ necessary calls. */
+
+ GLint n, maxNameLength;
+ GLchar *name;
+ GLint size;
+ GLenum type;
+
+ // obtain info regarding active attributes
+ GLTrace_glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &n);
+ GLTrace_glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxNameLength);
+
+ name = (GLchar *) malloc(maxNameLength);
+ for (int i = 0; i < n; i++) {
+ GLTrace_glGetActiveAttrib(program, i, maxNameLength, NULL, &size, &type, name);
+ }
+ free(name);
+
+ // obtain info regarding active uniforms
+ GLTrace_glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &n);
+ GLTrace_glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength);
+
+ name = (GLchar *) malloc(maxNameLength);
+ for (int i = 0; i < n; i++) {
+ GLTrace_glGetActiveUniform(program, i, maxNameLength, NULL, &size, &type, name);
+ }
+ free(name);
+}
+
+/** Given a glGetActive[Uniform|Attrib] call, obtain the location
+ * of the variable in the call.
+ */
+int getShaderVariableLocation(GLTraceContext *context, GLMessage *glmsg) {
+ GLMessage_Function func = glmsg->function();
+ if (func != GLMessage::glGetActiveAttrib && func != GLMessage::glGetActiveUniform) {
+ return -1;
+ }
+
+ int program = glmsg->args(0).intvalue(0);
+ GLchar *name = (GLchar*) glmsg->args(6).intvalue(0);
+
+ if (func == GLMessage::glGetActiveAttrib) {
+ return context->hooks->gl.glGetAttribLocation(program, name);
+ } else {
+ return context->hooks->gl.glGetUniformLocation(program, name);
+ }
+}
+
+void fixup_glGetActiveAttribOrUniform(GLMessage *glmsg, int location) {
+ /* void glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize,
+ GLsizei* length, GLint* size, GLenum* type, GLchar* name); */
+ /* void glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize,
+ GLsizei* length, GLint* size, GLenum* type, GLchar* name) */
+
+ fixup_GenericIntArray(3, 1, glmsg); // length
+ fixup_GenericIntArray(4, 1, glmsg); // size
+ fixup_GenericEnumArray(5, 1, glmsg); // type
+ fixup_CStringPtr(6, glmsg); // name
+
+ // The index argument in the glGetActive[Attrib|Uniform] functions
+ // does not correspond to the actual location index as used in
+ // glUniform*() or glVertexAttrib*() to actually upload the data.
+ // In order to make things simpler for the debugger, we also pass
+ // a hidden location argument that stores the actual location.
+ // append the location value to the end of the argument list
+ GLMessage_DataType *arg_location = glmsg->add_args();
+ arg_location->set_isarray(false);
+ arg_location->set_type(GLMessage::DataType::INT);
+ arg_location->add_intvalue(location);
+}
+
void fixupGLMessage(GLTraceContext *context, nsecs_t start, nsecs_t end, GLMessage *glmsg) {
// for all messages, set the current context id
glmsg->set_context_id(context->getId());
@@ -292,6 +401,19 @@
case GLMessage::glGenTextures: /* void glGenTextures(GLsizei n, GLuint *textures); */
fixup_glGenGeneric(glmsg);
break;
+ case GLMessage::glLinkProgram: /* void glLinkProgram(GLuint program); */
+ fixup_glLinkProgram(glmsg);
+ break;
+ case GLMessage::glGetActiveAttrib:
+ fixup_glGetActiveAttribOrUniform(glmsg, getShaderVariableLocation(context, glmsg));
+ break;
+ case GLMessage::glGetActiveUniform:
+ fixup_glGetActiveAttribOrUniform(glmsg, getShaderVariableLocation(context, glmsg));
+ break;
+ case GLMessage::glBindAttribLocation:
+ /* void glBindAttribLocation(GLuint program, GLuint index, const GLchar* name); */
+ fixup_CStringPtr(2, glmsg);
+ break;
case GLMessage::glGetAttribLocation:
case GLMessage::glGetUniformLocation:
/* int glGetAttribLocation(GLuint program, const GLchar* name) */
@@ -331,6 +453,38 @@
case GLMessage::glShaderSource:
fixup_glShaderSource(glmsg);
break;
+ case GLMessage::glUniform1iv:
+ /* void glUniform1iv(GLint location, GLsizei count, const GLint *value); */
+ fixup_glUniformGenericInteger(2, 1, glmsg);
+ break;
+ case GLMessage::glUniform2iv:
+ /* void glUniform2iv(GLint location, GLsizei count, const GLint *value); */
+ fixup_glUniformGenericInteger(2, 2, glmsg);
+ break;
+ case GLMessage::glUniform3iv:
+ /* void glUniform3iv(GLint location, GLsizei count, const GLint *value); */
+ fixup_glUniformGenericInteger(2, 3, glmsg);
+ break;
+ case GLMessage::glUniform4iv:
+ /* void glUniform4iv(GLint location, GLsizei count, const GLint *value); */
+ fixup_glUniformGenericInteger(2, 4, glmsg);
+ break;
+ case GLMessage::glUniform1fv:
+ /* void glUniform1fv(GLint location, GLsizei count, const GLfloat *value); */
+ fixup_glUniformGeneric(2, 1, glmsg);
+ break;
+ case GLMessage::glUniform2fv:
+ /* void glUniform2fv(GLint location, GLsizei count, const GLfloat *value); */
+ fixup_glUniformGeneric(2, 2, glmsg);
+ break;
+ case GLMessage::glUniform3fv:
+ /* void glUniform3fv(GLint location, GLsizei count, const GLfloat *value); */
+ fixup_glUniformGeneric(2, 3, glmsg);
+ break;
+ case GLMessage::glUniform4fv:
+ /* void glUniform4fv(GLint location, GLsizei count, const GLfloat *value); */
+ fixup_glUniformGeneric(2, 4, glmsg);
+ break;
case GLMessage::glUniformMatrix2fv:
/* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose,
const GLfloat* value) */
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
index 2d76455..aa27861 100644
--- a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
@@ -58,6 +58,7 @@
android:maxHeight="@dimen/status_bar_recents_app_icon_max_height"
android:scaleType="centerInside"
android:adjustViewBounds="true"
+ android:visibility="invisible"
/>
<TextView android:id="@+id/app_label"
diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
index b653fcd..bc389f9 100644
--- a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
@@ -81,6 +81,7 @@
android:maxHeight="@dimen/status_bar_recents_app_icon_max_height"
android:scaleType="centerInside"
android:adjustViewBounds="true"
+ android:visibility="invisible"
/>
<TextView android:id="@+id/app_description"
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
index cb26db00..333fcda 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
@@ -65,6 +65,7 @@
android:maxHeight="@dimen/status_bar_recents_app_icon_max_height"
android:scaleType="centerInside"
android:adjustViewBounds="true"
+ android:visibility="invisible"
/>
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 14ce266..cd8bd4e 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -236,6 +236,10 @@
public void onAnimationEnd(Animator animation) {
mCallback.onChildDismissed(view);
animView.setLayerType(View.LAYER_TYPE_NONE, null);
+ // Restore the alpha/translation parameters to what they were before swiping
+ // (for when these items are recycled)
+ animView.setAlpha(1f);
+ setTranslation(animView, 0f);
}
});
anim.addUpdateListener(new AnimatorUpdateListener() {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
index ad38a11..f8a4592 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
@@ -134,6 +134,7 @@
void jumpTo(boolean appearing) {
mContentView.setTranslationY(appearing ? 0 : mPanelHeight);
+ mScrimView.getBackground().setAlpha(appearing ? 255 : 0);
}
public void setPanelHeight(int h) {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
index 4145fc4..92f4ca9 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -16,12 +16,6 @@
package com.android.systemui.recent;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
@@ -36,15 +30,17 @@
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Process;
-import android.os.SystemClock;
-import android.util.DisplayMetrics;
import android.util.Log;
-import android.util.LruCache;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.tablet.TabletStatusBar;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
public class RecentTasksLoader {
static final String TAG = "RecentTasksLoader";
static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false;
@@ -55,11 +51,14 @@
private Context mContext;
private RecentsPanelView mRecentsPanel;
- private AsyncTask<Void, Integer, Void> mThumbnailLoader;
+ private AsyncTask<Void, ArrayList<TaskDescription>, Void> mTaskLoader;
+ private AsyncTask<Void, TaskDescription, Void> mThumbnailLoader;
private final Handler mHandler;
private int mIconDpi;
private Bitmap mDefaultThumbnailBackground;
+ private Bitmap mDefaultIconBackground;
+ private int mNumTasksInFirstScreenful;
public RecentTasksLoader(Context context) {
mContext = context;
@@ -76,12 +75,20 @@
mIconDpi = res.getDisplayMetrics().densityDpi;
}
+ // Render default icon (just a blank image)
+ int defaultIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.app_icon_size);
+ int iconSize = (int) (defaultIconSize * mIconDpi / res.getDisplayMetrics().densityDpi);
+ mDefaultIconBackground = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888);
+
// Render the default thumbnail background
- int width = (int) res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
- int height = (int) res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
+ int thumbnailWidth =
+ (int) res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
+ int thumbnailHeight =
+ (int) res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
int color = res.getColor(R.drawable.status_bar_recents_app_thumbnail_background);
- mDefaultThumbnailBackground = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ mDefaultThumbnailBackground =
+ Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(mDefaultThumbnailBackground);
c.drawColor(color);
@@ -95,12 +102,17 @@
public void setRecentsPanel(RecentsPanelView recentsPanel) {
mRecentsPanel = recentsPanel;
+ mNumTasksInFirstScreenful = mRecentsPanel.numItemsInOneScreenful();
}
public Bitmap getDefaultThumbnail() {
return mDefaultThumbnailBackground;
}
+ public Bitmap getDefaultIcon() {
+ return mDefaultIconBackground;
+ }
+
// Create an TaskDescription, returning null if the title or icon is null, or if it's the
// home activity
TaskDescription createTaskDescription(int taskId, int persistentTaskId, Intent baseIntent,
@@ -114,6 +126,12 @@
homeInfo = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME)
.resolveActivityInfo(pm, 0);
}
+ // Don't load the current home activity.
+ if (homeInfo != null
+ && homeInfo.packageName.equals(intent.getComponent().getPackageName())
+ && homeInfo.name.equals(intent.getComponent().getClassName())) {
+ return null;
+ }
intent.setFlags((intent.getFlags()&~Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
| Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -121,9 +139,8 @@
if (resolveInfo != null) {
final ActivityInfo info = resolveInfo.activityInfo;
final String title = info.loadLabel(pm).toString();
- Drawable icon = getFullResIcon(resolveInfo, pm);
- if (title != null && title.length() > 0 && icon != null) {
+ if (title != null && title.length() > 0) {
if (DEBUG) Log.v(TAG, "creating activity desc for id="
+ persistentTaskId + ", label=" + title);
@@ -131,14 +148,6 @@
persistentTaskId, resolveInfo, baseIntent, info.packageName,
description);
item.setLabel(title);
- item.setIcon(icon);
-
- // Don't load the current home activity.
- if (homeInfo != null
- && homeInfo.packageName.equals(intent.getComponent().getPackageName())
- && homeInfo.name.equals(intent.getComponent().getClassName())) {
- return null;
- }
return item;
} else {
@@ -148,10 +157,12 @@
return null;
}
- void loadThumbnail(TaskDescription td) {
+ void loadThumbnailAndIcon(TaskDescription td) {
final ActivityManager am = (ActivityManager)
mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ final PackageManager pm = mContext.getPackageManager();
ActivityManager.TaskThumbnails thumbs = am.getTaskThumbnails(td.persistentTaskId);
+ Drawable icon = getFullResIcon(td.resolveInfo, pm);
if (DEBUG) Log.v(TAG, "Loaded bitmap for task "
+ td + ": " + thumbs.mainThumbnail);
@@ -161,6 +172,10 @@
} else {
td.setThumbnail(mDefaultThumbnailBackground);
}
+ if (icon != null) {
+ td.setIcon(icon);
+ }
+ td.setLoaded(true);
}
}
@@ -194,111 +209,149 @@
return getFullResDefaultActivityIcon();
}
- public void cancelLoadingThumbnails() {
+ public void cancelLoadingThumbnailsAndIcons() {
+ if (mTaskLoader != null) {
+ mTaskLoader.cancel(false);
+ mTaskLoader = null;
+ }
if (mThumbnailLoader != null) {
mThumbnailLoader.cancel(false);
mThumbnailLoader = null;
}
}
- // return a snapshot of the current list of recent apps
- ArrayList<TaskDescription> getRecentTasks() {
- cancelLoadingThumbnails();
-
- ArrayList<TaskDescription> tasks = new ArrayList<TaskDescription>();
- final PackageManager pm = mContext.getPackageManager();
- final ActivityManager am = (ActivityManager)
+ public void loadTasksInBackground() {
+ // cancel all previous loading of tasks and thumbnails
+ cancelLoadingThumbnailsAndIcons();
+ final LinkedBlockingQueue<TaskDescription> tasksWaitingForThumbnails =
+ new LinkedBlockingQueue<TaskDescription>();
+ final ArrayList<TaskDescription> taskDescriptionsWaitingToLoad =
+ new ArrayList<TaskDescription>();
+ mTaskLoader = new AsyncTask<Void, ArrayList<TaskDescription>, Void>() {
+ @Override
+ protected void onProgressUpdate(ArrayList<TaskDescription>... values) {
+ if (!isCancelled()) {
+ ArrayList<TaskDescription> newTasks = values[0];
+ // do a callback to RecentsPanelView to let it know we have more values
+ // how do we let it know we're all done? just always call back twice
+ mRecentsPanel.onTasksLoaded(newTasks);
+ }
+ }
+ @Override
+ protected Void doInBackground(Void... params) {
+ // We load in two stages: first, we update progress with just the first screenful
+ // of items. Then, we update with the rest of the items
+ final int origPri = Process.getThreadPriority(Process.myTid());
+ Process.setThreadPriority(Process.THREAD_GROUP_BG_NONINTERACTIVE);
+ final PackageManager pm = mContext.getPackageManager();
+ final ActivityManager am = (ActivityManager)
mContext.getSystemService(Context.ACTIVITY_SERVICE);
- final List<ActivityManager.RecentTaskInfo> recentTasks =
- am.getRecentTasks(MAX_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE);
+ final List<ActivityManager.RecentTaskInfo> recentTasks =
+ am.getRecentTasks(MAX_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE);
+ int numTasks = recentTasks.size();
+ ActivityInfo homeInfo = new Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_HOME).resolveActivityInfo(pm, 0);
- ActivityInfo homeInfo = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME)
- .resolveActivityInfo(pm, 0);
+ boolean firstScreenful = true;
+ ArrayList<TaskDescription> tasks = new ArrayList<TaskDescription>();
- HashSet<Integer> recentTasksToKeepInCache = new HashSet<Integer>();
- int numTasks = recentTasks.size();
-
- // skip the first task - assume it's either the home screen or the current activity.
- final int first = 1;
- recentTasksToKeepInCache.add(recentTasks.get(0).persistentId);
- for (int i = first, index = 0; i < numTasks && (index < MAX_TASKS); ++i) {
- final ActivityManager.RecentTaskInfo recentInfo = recentTasks.get(i);
-
- TaskDescription item = createTaskDescription(recentInfo.id,
- recentInfo.persistentId, recentInfo.baseIntent,
- recentInfo.origActivity, recentInfo.description, homeInfo);
-
- if (item != null) {
- tasks.add(item);
- ++index;
- }
- }
-
- // when we're not using the TaskDescription cache, we load the thumbnails in the
- // background
- loadThumbnailsInBackground(new ArrayList<TaskDescription>(tasks));
- return tasks;
- }
-
- private void loadThumbnailsInBackground(final ArrayList<TaskDescription> descriptions) {
- if (descriptions.size() > 0) {
- if (DEBUG) Log.v(TAG, "Showing " + descriptions.size() + " tasks");
- loadThumbnail(descriptions.get(0));
- if (descriptions.size() > 1) {
- mThumbnailLoader = new AsyncTask<Void, Integer, Void>() {
- @Override
- protected void onProgressUpdate(Integer... values) {
- final TaskDescription td = descriptions.get(values[0]);
- if (!isCancelled()) {
- mRecentsPanel.onTaskThumbnailLoaded(td);
- }
- // This is to prevent the loader thread from getting ahead
- // of our UI updates.
- mHandler.post(new Runnable() {
- @Override public void run() {
- synchronized (td) {
- td.notifyAll();
- }
- }
- });
+ // skip the first task - assume it's either the home screen or the current activity.
+ final int first = 1;
+ for (int i = first, index = 0; i < numTasks && (index < MAX_TASKS); ++i) {
+ if (isCancelled()) {
+ break;
}
+ final ActivityManager.RecentTaskInfo recentInfo = recentTasks.get(i);
+ TaskDescription item = createTaskDescription(recentInfo.id,
+ recentInfo.persistentId, recentInfo.baseIntent,
+ recentInfo.origActivity, recentInfo.description, homeInfo);
- @Override
- protected Void doInBackground(Void... params) {
- final int origPri = Process.getThreadPriority(Process.myTid());
- Process.setThreadPriority(Process.THREAD_GROUP_BG_NONINTERACTIVE);
- long nextTime = SystemClock.uptimeMillis();
- for (int i=1; i<descriptions.size(); i++) {
- TaskDescription td = descriptions.get(i);
- loadThumbnail(td);
- long now = SystemClock.uptimeMillis();
- nextTime += 0;
- if (nextTime > now) {
- try {
- Thread.sleep(nextTime-now);
- } catch (InterruptedException e) {
- }
- }
-
- if (isCancelled()) {
+ if (item != null) {
+ while (true) {
+ try {
+ tasksWaitingForThumbnails.put(item);
break;
- }
- synchronized (td) {
- publishProgress(i);
- try {
- td.wait(500);
- } catch (InterruptedException e) {
- }
+ } catch (InterruptedException e) {
}
}
- Process.setThreadPriority(origPri);
- return null;
+ tasks.add(item);
+ if (firstScreenful && tasks.size() == mNumTasksInFirstScreenful) {
+ publishProgress(tasks);
+ tasks = new ArrayList<TaskDescription>();
+ firstScreenful = false;
+ //break;
+ }
+ ++index;
}
- };
- mThumbnailLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ if (!isCancelled()) {
+ publishProgress(tasks);
+ if (firstScreenful) {
+ // always should publish two updates
+ publishProgress(new ArrayList<TaskDescription>());
+ }
+ }
+
+ while (true) {
+ try {
+ tasksWaitingForThumbnails.put(new TaskDescription());
+ break;
+ } catch (InterruptedException e) {
+ }
+ }
+
+ Process.setThreadPriority(origPri);
+ return null;
}
- }
+ };
+ mTaskLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ loadThumbnailsAndIconsInBackground(tasksWaitingForThumbnails);
}
+ private void loadThumbnailsAndIconsInBackground(
+ final BlockingQueue<TaskDescription> tasksWaitingForThumbnails) {
+ // continually read items from tasksWaitingForThumbnails and load
+ // thumbnails and icons for them. finish thread when cancelled or there
+ // is a null item in tasksWaitingForThumbnails
+ mThumbnailLoader = new AsyncTask<Void, TaskDescription, Void>() {
+ @Override
+ protected void onProgressUpdate(TaskDescription... values) {
+ if (!isCancelled()) {
+ TaskDescription td = values[0];
+ mRecentsPanel.onTaskThumbnailLoaded(td);
+ }
+ }
+ @Override
+ protected Void doInBackground(Void... params) {
+ final int origPri = Process.getThreadPriority(Process.myTid());
+ Process.setThreadPriority(Process.THREAD_GROUP_BG_NONINTERACTIVE);
+
+ while (true) {
+ if (isCancelled()) {
+ break;
+ }
+ TaskDescription td = null;
+ while (td == null) {
+ try {
+ td = tasksWaitingForThumbnails.take();
+ } catch (InterruptedException e) {
+ }
+ }
+ if (td.isNull()) {
+ break;
+ }
+ loadThumbnailAndIcon(td);
+ synchronized(td) {
+ publishProgress(td);
+ }
+ }
+
+ Process.setThreadPriority(origPri);
+ return null;
+ }
+ };
+ mThumbnailLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
index f971d2d..4718a17 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
@@ -22,11 +22,18 @@
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
+import android.view.View.MeasureSpec;
+import android.view.View.OnClickListener;
+import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
+import android.view.ViewConfiguration;
+import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
@@ -34,6 +41,8 @@
import com.android.systemui.SwipeHelper;
import com.android.systemui.recent.RecentsPanelView.TaskDescriptionAdapter;
+import java.util.ArrayList;
+
public class RecentsHorizontalScrollView extends HorizontalScrollView
implements SwipeHelper.Callback {
private static final String TAG = RecentsPanelView.TAG;
@@ -44,6 +53,8 @@
protected int mLastScrollPosition;
private SwipeHelper mSwipeHelper;
private RecentsScrollViewPerformanceHelper mPerformanceHelper;
+ private ArrayList<View> mRecycledViews;
+ private int mNumItemsInOneScreenful;
public RecentsHorizontalScrollView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
@@ -51,6 +62,7 @@
float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
mSwipeHelper = new SwipeHelper(SwipeHelper.Y, this, densityScale, pagingTouchSlop);
mPerformanceHelper = RecentsScrollViewPerformanceHelper.create(context, attrs, this, false);
+ mRecycledViews = new ArrayList<View>();
}
private int scrollPositionOfMostRecent() {
@@ -58,9 +70,23 @@
}
private void update() {
+ for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
+ View v = mLinearLayout.getChildAt(i);
+ mRecycledViews.add(v);
+ mAdapter.recycleView(v);
+ }
+ LayoutTransition transitioner = getLayoutTransition();
+ setLayoutTransition(null);
+
mLinearLayout.removeAllViews();
for (int i = 0; i < mAdapter.getCount(); i++) {
- final View view = mAdapter.getView(i, null, mLinearLayout);
+ View old = null;
+ if (mRecycledViews.size() != 0) {
+ old = mRecycledViews.remove(mRecycledViews.size() - 1);
+ old.setVisibility(VISIBLE);
+ }
+
+ final View view = mAdapter.getView(i, old, mLinearLayout);
if (mPerformanceHelper != null) {
mPerformanceHelper.addViewCallback(view);
@@ -87,7 +113,8 @@
}
};
- final View thumbnailView = view.findViewById(R.id.app_thumbnail);
+ RecentsPanelView.ViewHolder holder = (RecentsPanelView.ViewHolder) view.getTag();
+ final View thumbnailView = holder.thumbnailView;
OnLongClickListener longClickListener = new OnLongClickListener() {
public boolean onLongClick(View v) {
final View anchorView = view.findViewById(R.id.app_description);
@@ -107,13 +134,21 @@
appTitle.setOnTouchListener(noOpListener);
mLinearLayout.addView(view);
}
+ setLayoutTransition(transitioner);
+
// Scroll to end after layout.
- post(new Runnable() {
- public void run() {
- mLastScrollPosition = scrollPositionOfMostRecent();
- scrollTo(mLastScrollPosition, 0);
- }
- });
+ final ViewTreeObserver observer = getViewTreeObserver();
+
+ final OnGlobalLayoutListener updateScroll = new OnGlobalLayoutListener() {
+ public void onGlobalLayout() {
+ mLastScrollPosition = scrollPositionOfMostRecent();
+ scrollTo(mLastScrollPosition, 0);
+ if (observer.isAlive()) {
+ observer.removeOnGlobalLayoutListener(this);
+ }
+ }
+ };
+ observer.addOnGlobalLayoutListener(updateScroll);
}
@Override
@@ -142,8 +177,10 @@
}
public void onChildDismissed(View v) {
+ mRecycledViews.add(v);
mLinearLayout.removeView(v);
mCallback.handleSwipe(v);
+ v.setActivated(false);
}
public void onBeginDrag(View v) {
@@ -315,6 +352,24 @@
update();
}
});
+ DisplayMetrics dm = getResources().getDisplayMetrics();
+ int childWidthMeasureSpec =
+ MeasureSpec.makeMeasureSpec(dm.widthPixels, MeasureSpec.AT_MOST);
+ int childheightMeasureSpec =
+ MeasureSpec.makeMeasureSpec(dm.heightPixels, MeasureSpec.AT_MOST);
+ View child = mAdapter.createView(mLinearLayout);
+ child.measure(childWidthMeasureSpec, childheightMeasureSpec);
+ mNumItemsInOneScreenful =
+ (int) FloatMath.ceil(dm.widthPixels / (float) child.getMeasuredWidth());
+ mRecycledViews.add(child);
+
+ for (int i = 0; i < mNumItemsInOneScreenful - 1; i++) {
+ mRecycledViews.add(mAdapter.createView(mLinearLayout));
+ }
+ }
+
+ public int numItemsInOneScreenful() {
+ return mNumItemsInOneScreenful;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index a10e363..8706f10 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -27,6 +27,7 @@
import android.graphics.Matrix;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.provider.Settings;
import android.util.AttributeSet;
@@ -36,18 +37,18 @@
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewGroup;
+import android.view.ViewRootImpl;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
+import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.PopupMenu;
-import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
@@ -59,7 +60,7 @@
import java.util.ArrayList;
-public class RecentsPanelView extends RelativeLayout implements OnItemClickListener, RecentsCallback,
+public class RecentsPanelView extends FrameLayout implements OnItemClickListener, RecentsCallback,
StatusBarPanel, Animator.AnimatorListener, View.OnTouchListener {
static final String TAG = "RecentsPanelView";
static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false;
@@ -71,6 +72,10 @@
private StatusBarTouchProxy mStatusBarTouchProxy;
private boolean mShowing;
+ private boolean mWaitingToShow;
+ private boolean mWaitingToShowAnimated;
+ private boolean mReadyToShow;
+ private int mNumItemsWaitingForThumbnailsAndIcons;
private Choreographer mChoreo;
OnRecentsPanelVisibilityChangedListener mVisibilityChangedListener;
@@ -104,6 +109,7 @@
TextView labelView;
TextView descriptionView;
TaskDescription taskDescription;
+ boolean loadedThumbnailAndIcon;
}
/* package */ final class TaskDescriptionAdapter extends BaseAdapter {
@@ -125,42 +131,82 @@
return position; // we just need something unique for this position
}
- public View getView(int position, View convertView, ViewGroup parent) {
- ViewHolder holder;
- if (convertView == null) {
- convertView = mInflater.inflate(R.layout.status_bar_recent_item, parent, false);
- holder = new ViewHolder();
- holder.thumbnailView = convertView.findViewById(R.id.app_thumbnail);
- holder.thumbnailViewImage = (ImageView) convertView.findViewById(
- R.id.app_thumbnail_image);
- // If we set the default thumbnail now, we avoid an onLayout when we update
- // the thumbnail later (if they both have the same dimensions)
+ public View createView(ViewGroup parent) {
+ View convertView = mInflater.inflate(R.layout.status_bar_recent_item, parent, false);
+ ViewHolder holder = new ViewHolder();
+ holder.thumbnailView = convertView.findViewById(R.id.app_thumbnail);
+ holder.thumbnailViewImage =
+ (ImageView) convertView.findViewById(R.id.app_thumbnail_image);
+ // If we set the default thumbnail now, we avoid an onLayout when we update
+ // the thumbnail later (if they both have the same dimensions)
+ if (mRecentTasksLoader != null) {
updateThumbnail(holder, mRecentTasksLoader.getDefaultThumbnail(), false, false);
-
- holder.iconView = (ImageView) convertView.findViewById(R.id.app_icon);
- holder.labelView = (TextView) convertView.findViewById(R.id.app_label);
- holder.descriptionView = (TextView) convertView.findViewById(R.id.app_description);
-
- convertView.setTag(holder);
- } else {
- holder = (ViewHolder) convertView.getTag();
}
+ holder.iconView = (ImageView) convertView.findViewById(R.id.app_icon);
+ if (mRecentTasksLoader != null) {
+ holder.iconView.setImageBitmap(mRecentTasksLoader.getDefaultIcon());
+ }
+ holder.labelView = (TextView) convertView.findViewById(R.id.app_label);
+ holder.descriptionView = (TextView) convertView.findViewById(R.id.app_description);
+
+ convertView.setTag(holder);
+ return convertView;
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView = createView(parent);
+ }
+ ViewHolder holder = (ViewHolder) convertView.getTag();
// index is reverse since most recent appears at the bottom...
final int index = mRecentTaskDescriptions.size() - position - 1;
final TaskDescription td = mRecentTaskDescriptions.get(index);
- holder.iconView.setImageDrawable(td.getIcon());
+
holder.labelView.setText(td.getLabel());
holder.thumbnailView.setContentDescription(td.getLabel());
- updateThumbnail(holder, td.getThumbnail(), true, false);
+ holder.loadedThumbnailAndIcon = td.isLoaded();
+ if (td.isLoaded()) {
+ updateThumbnail(holder, td.getThumbnail(), true, false);
+ updateIcon(holder, td.getIcon(), true, false);
+ mNumItemsWaitingForThumbnailsAndIcons--;
+ }
holder.thumbnailView.setTag(td);
holder.thumbnailView.setOnLongClickListener(new OnLongClickDelegate(convertView));
holder.taskDescription = td;
-
return convertView;
}
+
+ public void recycleView(View v) {
+ ViewHolder holder = (ViewHolder) v.getTag();
+ updateThumbnail(holder, mRecentTasksLoader.getDefaultThumbnail(), false, false);
+ holder.iconView.setImageBitmap(mRecentTasksLoader.getDefaultIcon());
+ holder.iconView.setVisibility(INVISIBLE);
+ holder.labelView.setText(null);
+ holder.thumbnailView.setContentDescription(null);
+ holder.thumbnailView.setTag(null);
+ holder.thumbnailView.setOnLongClickListener(null);
+ holder.thumbnailView.setVisibility(INVISIBLE);
+ holder.taskDescription = null;
+ holder.loadedThumbnailAndIcon = false;
+ }
+ }
+
+ public int numItemsInOneScreenful() {
+ if (mRecentsContainer instanceof RecentsHorizontalScrollView){
+ RecentsHorizontalScrollView scrollView
+ = (RecentsHorizontalScrollView) mRecentsContainer;
+ return scrollView.numItemsInOneScreenful();
+ } else if (mRecentsContainer instanceof RecentsVerticalScrollView){
+ RecentsVerticalScrollView scrollView
+ = (RecentsVerticalScrollView) mRecentsContainer;
+ return scrollView.numItemsInOneScreenful();
+ }
+ else {
+ throw new IllegalArgumentException("missing Recents[Horizontal]ScrollView");
+ }
}
@Override
@@ -192,15 +238,31 @@
}
public void show(boolean show, boolean animate) {
- show(show, animate, null);
+ if (show) {
+ mWaitingToShow = true;
+ mWaitingToShowAnimated = animate;
+ showIfReady();
+ } else {
+ show(show, animate, null, false);
+ }
+ }
+
+ private void showIfReady() {
+ // mWaitingToShow = there was a touch up on the recents button
+ // mReadyToShow = we've created views for the first screenful of items
+ if (mWaitingToShow && mReadyToShow) { // && mNumItemsWaitingForThumbnailsAndIcons <= 0
+ show(true, mWaitingToShowAnimated, null, false);
+ }
}
public void show(boolean show, boolean animate,
- ArrayList<TaskDescription> recentTaskDescriptions) {
+ ArrayList<TaskDescription> recentTaskDescriptions, boolean firstScreenful) {
+ // For now, disable animations. We may want to re-enable in the future
+ animate = false;
if (show) {
// Need to update list of recent apps before we set visibility so this view's
// content description is updated before it gets focus for TalkBack mode
- refreshRecentTasksList(recentTaskDescriptions);
+ refreshRecentTasksList(recentTaskDescriptions, firstScreenful);
// if there are no apps, either bring up a "No recent apps" message, or just
// quit early
@@ -209,19 +271,24 @@
mRecentsNoApps.setVisibility(noApps ? View.VISIBLE : View.INVISIBLE);
} else {
if (noApps) {
- if (DEBUG) Log.v(TAG, "Nothing to show");
+ if (DEBUG) Log.v(TAG, "Nothing to show");
// Need to set recent tasks to dirty so that next time we load, we
// refresh the list of tasks
- mRecentTasksLoader.cancelLoadingThumbnails();
+ mRecentTasksLoader.cancelLoadingThumbnailsAndIcons();
mRecentTasksDirty = true;
+
+ mWaitingToShow = false;
+ mReadyToShow = false;
return;
}
}
} else {
// Need to set recent tasks to dirty so that next time we load, we
// refresh the list of tasks
- mRecentTasksLoader.cancelLoadingThumbnails();
+ mRecentTasksLoader.cancelLoadingThumbnailsAndIcons();
mRecentTasksDirty = true;
+ mWaitingToShow = false;
+ mReadyToShow = false;
}
if (animate) {
if (mShowing != show) {
@@ -385,7 +452,6 @@
throw new IllegalArgumentException("missing Recents[Horizontal]ScrollView");
}
-
mRecentsScrim = findViewById(R.id.recents_bg_protect);
mRecentsNoApps = findViewById(R.id.recents_no_apps);
mChoreo = new Choreographer(this, mRecentsScrim, mRecentsContainer, mRecentsNoApps, this);
@@ -425,6 +491,20 @@
}
}
+
+ private void updateIcon(ViewHolder h, Drawable icon, boolean show, boolean anim) {
+ if (icon != null) {
+ h.iconView.setImageDrawable(icon);
+ if (show && h.iconView.getVisibility() != View.VISIBLE) {
+ if (anim) {
+ h.iconView.setAnimation(
+ AnimationUtils.loadAnimation(mContext, R.anim.recent_appear));
+ }
+ h.iconView.setVisibility(View.VISIBLE);
+ }
+ }
+ }
+
private void updateThumbnail(ViewHolder h, Bitmap thumbnail, boolean show, boolean anim) {
if (thumbnail != null) {
// Should remove the default image in the frame
@@ -458,31 +538,36 @@
}
}
- void onTaskThumbnailLoaded(TaskDescription ad) {
- synchronized (ad) {
+ void onTaskThumbnailLoaded(TaskDescription td) {
+ synchronized (td) {
if (mRecentsContainer != null) {
ViewGroup container = mRecentsContainer;
if (container instanceof HorizontalScrollView
|| container instanceof ScrollView) {
- container = (ViewGroup)container.findViewById(
+ container = (ViewGroup) container.findViewById(
R.id.recents_linear_layout);
}
// Look for a view showing this thumbnail, to update.
- for (int i=0; i<container.getChildCount(); i++) {
+ for (int i=0; i < container.getChildCount(); i++) {
View v = container.getChildAt(i);
if (v.getTag() instanceof ViewHolder) {
ViewHolder h = (ViewHolder)v.getTag();
- if (h.taskDescription == ad) {
+ if (!h.loadedThumbnailAndIcon && h.taskDescription == td) {
// only fade in the thumbnail if recents is already visible-- we
// show it immediately otherwise
- boolean animateShow = mShowing &&
- mRecentsContainer.getAlpha() > ViewConfiguration.ALPHA_THRESHOLD;
- updateThumbnail(h, ad.getThumbnail(), true, animateShow);
+ //boolean animateShow = mShowing &&
+ // mRecentsContainer.getAlpha() > ViewConfiguration.ALPHA_THRESHOLD;
+ boolean animateShow = false;
+ updateIcon(h, td.getIcon(), true, animateShow);
+ updateThumbnail(h, td.getThumbnail(), true, animateShow);
+ h.loadedThumbnailAndIcon = true;
+ mNumItemsWaitingForThumbnailsAndIcons--;
}
}
}
}
- }
+ }
+ showIfReady();
}
// additional optimization when we have sofware system buttons - start loading the recent
@@ -516,7 +601,7 @@
public void clearRecentTasksList() {
// Clear memory used by screenshots
if (mRecentTaskDescriptions != null) {
- mRecentTasksLoader.cancelLoadingThumbnails();
+ mRecentTasksLoader.cancelLoadingThumbnailsAndIcons();
mRecentTaskDescriptions.clear();
mListAdapter.notifyDataSetInvalidated();
mRecentTasksDirty = true;
@@ -524,26 +609,50 @@
}
public void refreshRecentTasksList() {
- refreshRecentTasksList(null);
+ refreshRecentTasksList(null, false);
}
- private void refreshRecentTasksList(ArrayList<TaskDescription> recentTasksList) {
+ private void refreshRecentTasksList(
+ ArrayList<TaskDescription> recentTasksList, boolean firstScreenful) {
if (mRecentTasksDirty) {
if (recentTasksList != null) {
- mRecentTaskDescriptions = recentTasksList;
+ mFirstScreenful = true;
+ onTasksLoaded(recentTasksList);
} else {
- mRecentTaskDescriptions = mRecentTasksLoader.getRecentTasks();
+ mFirstScreenful = true;
+ mRecentTasksLoader.loadTasksInBackground();
}
- mListAdapter.notifyDataSetInvalidated();
- updateUiElements(getResources().getConfiguration());
mRecentTasksDirty = false;
}
}
+ boolean mFirstScreenful;
+ public void onTasksLoaded(ArrayList<TaskDescription> tasks) {
+ if (!mFirstScreenful && tasks.size() == 0) {
+ return;
+ }
+ mNumItemsWaitingForThumbnailsAndIcons =
+ mFirstScreenful ? tasks.size() : mRecentTaskDescriptions.size();
+ if (mRecentTaskDescriptions == null) {
+ mRecentTaskDescriptions = new ArrayList(tasks);
+ } else {
+ mRecentTaskDescriptions.addAll(tasks);
+ }
+ mListAdapter.notifyDataSetInvalidated();
+ updateUiElements(getResources().getConfiguration());
+ mReadyToShow = true;
+ mFirstScreenful = false;
+ showIfReady();
+ }
+
public ArrayList<TaskDescription> getRecentTasksList() {
return mRecentTaskDescriptions;
}
+ public boolean getFirstScreenful() {
+ return mFirstScreenful;
+ }
+
private void updateUiElements(Configuration config) {
final int items = mRecentTaskDescriptions.size();
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
index dc13092..0605c4c 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
@@ -22,10 +22,18 @@
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
+import android.view.View.MeasureSpec;
+import android.view.View.OnClickListener;
+import android.view.View.OnLongClickListener;
+import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
+import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.LinearLayout;
import android.widget.ScrollView;
@@ -33,6 +41,8 @@
import com.android.systemui.SwipeHelper;
import com.android.systemui.recent.RecentsPanelView.TaskDescriptionAdapter;
+import java.util.ArrayList;
+
public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper.Callback {
private static final String TAG = RecentsPanelView.TAG;
private static final boolean DEBUG = RecentsPanelView.DEBUG;
@@ -42,6 +52,8 @@
protected int mLastScrollPosition;
private SwipeHelper mSwipeHelper;
private RecentsScrollViewPerformanceHelper mPerformanceHelper;
+ private ArrayList<View> mRecycledViews;
+ private int mNumItemsInOneScreenful;
public RecentsVerticalScrollView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
@@ -50,6 +62,7 @@
mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop);
mPerformanceHelper = RecentsScrollViewPerformanceHelper.create(context, attrs, this, true);
+ mRecycledViews = new ArrayList<View>();
}
private int scrollPositionOfMostRecent() {
@@ -57,77 +70,91 @@
}
private void update() {
+ for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
+ View v = mLinearLayout.getChildAt(i);
+ mRecycledViews.add(v);
+ mAdapter.recycleView(v);
+ }
+ LayoutTransition transitioner = getLayoutTransition();
+ setLayoutTransition(null);
+
mLinearLayout.removeAllViews();
// Once we can clear the data associated with individual item views,
// we can get rid of the removeAllViews() and the code below will
// recycle them.
for (int i = 0; i < mAdapter.getCount(); i++) {
View old = null;
- if (i < mLinearLayout.getChildCount()) {
- old = mLinearLayout.getChildAt(i);
- old.setVisibility(View.VISIBLE);
+ if (mRecycledViews.size() != 0) {
+ old = mRecycledViews.remove(mRecycledViews.size() - 1);
+ old.setVisibility(VISIBLE);
}
+
final View view = mAdapter.getView(i, old, mLinearLayout);
if (mPerformanceHelper != null) {
mPerformanceHelper.addViewCallback(view);
}
- if (old == null) {
- OnTouchListener noOpListener = new OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- return true;
- }
- };
+ OnTouchListener noOpListener = new OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return true;
+ }
+ };
- view.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- mCallback.dismiss();
- }
- });
- // We don't want a click sound when we dimiss recents
- view.setSoundEffectsEnabled(false);
+ view.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ mCallback.dismiss();
+ }
+ });
+ // We don't want a click sound when we dimiss recents
+ view.setSoundEffectsEnabled(false);
- OnClickListener launchAppListener = new OnClickListener() {
- public void onClick(View v) {
- mCallback.handleOnClick(view);
- }
- };
+ OnClickListener launchAppListener = new OnClickListener() {
+ public void onClick(View v) {
+ mCallback.handleOnClick(view);
+ }
+ };
- final View thumbnailView = view.findViewById(R.id.app_thumbnail);
- OnLongClickListener longClickListener = new OnLongClickListener() {
- public boolean onLongClick(View v) {
- final View anchorView = view.findViewById(R.id.app_description);
- mCallback.handleLongPress(view, anchorView, thumbnailView);
- return true;
- }
- };
- thumbnailView.setClickable(true);
- thumbnailView.setOnClickListener(launchAppListener);
- thumbnailView.setOnLongClickListener(longClickListener);
+ RecentsPanelView.ViewHolder holder = (RecentsPanelView.ViewHolder) view.getTag();
+ final View thumbnailView = holder.thumbnailView;
+ OnLongClickListener longClickListener = new OnLongClickListener() {
+ public boolean onLongClick(View v) {
+ final View anchorView = view.findViewById(R.id.app_description);
+ mCallback.handleLongPress(view, anchorView, thumbnailView);
+ return true;
+ }
+ };
+ thumbnailView.setClickable(true);
+ thumbnailView.setOnClickListener(launchAppListener);
+ thumbnailView.setOnLongClickListener(longClickListener);
- // We don't want to dismiss recents if a user clicks on the app title
- // (we also don't want to launch the app either, though, because the
- // app title is a small target and doesn't have great click feedback)
- final View appTitle = view.findViewById(R.id.app_label);
- appTitle.setContentDescription(" ");
- appTitle.setOnTouchListener(noOpListener);
- final View calloutLine = view.findViewById(R.id.recents_callout_line);
- calloutLine.setOnTouchListener(noOpListener);
- mLinearLayout.addView(view);
- }
+ // We don't want to dismiss recents if a user clicks on the app title
+ // (we also don't want to launch the app either, though, because the
+ // app title is a small target and doesn't have great click feedback)
+ final View appTitle = view.findViewById(R.id.app_label);
+ appTitle.setContentDescription(" ");
+ appTitle.setOnTouchListener(noOpListener);
+ final View calloutLine = view.findViewById(R.id.recents_callout_line);
+ calloutLine.setOnTouchListener(noOpListener);
+
+ mLinearLayout.addView(view);
}
- for (int i = mAdapter.getCount(); i < mLinearLayout.getChildCount(); i++) {
- mLinearLayout.getChildAt(i).setVisibility(View.GONE);
- }
+ setLayoutTransition(transitioner);
+
// Scroll to end after layout.
- post(new Runnable() {
- public void run() {
- mLastScrollPosition = scrollPositionOfMostRecent();
- scrollTo(0, mLastScrollPosition);
- }
- });
+ final ViewTreeObserver observer = getViewTreeObserver();
+
+ final OnGlobalLayoutListener updateScroll = new OnGlobalLayoutListener() {
+ public void onGlobalLayout() {
+ mLastScrollPosition = scrollPositionOfMostRecent();
+ scrollTo(0, mLastScrollPosition);
+ if (observer.isAlive()) {
+ observer.removeOnGlobalLayoutListener(this);
+ }
+ }
+ };
+ observer.addOnGlobalLayoutListener(updateScroll);
}
@Override
@@ -156,8 +183,10 @@
}
public void onChildDismissed(View v) {
+ mRecycledViews.add(v);
mLinearLayout.removeView(v);
mCallback.handleSwipe(v);
+ v.setActivated(false);
}
public void onBeginDrag(View v) {
@@ -330,6 +359,25 @@
update();
}
});
+
+ DisplayMetrics dm = getResources().getDisplayMetrics();
+ int childWidthMeasureSpec =
+ MeasureSpec.makeMeasureSpec(dm.widthPixels, MeasureSpec.AT_MOST);
+ int childheightMeasureSpec =
+ MeasureSpec.makeMeasureSpec(dm.heightPixels, MeasureSpec.AT_MOST);
+ View child = mAdapter.createView(mLinearLayout);
+ child.measure(childWidthMeasureSpec, childheightMeasureSpec);
+ mNumItemsInOneScreenful =
+ (int) FloatMath.ceil(dm.heightPixels / (float) child.getMeasuredHeight());
+ mRecycledViews.add(child);
+
+ for (int i = 0; i < mNumItemsInOneScreenful - 1; i++) {
+ mRecycledViews.add(mAdapter.createView(mLinearLayout));
+ }
+ }
+
+ public int numItemsInOneScreenful() {
+ return mNumItemsInOneScreenful;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java b/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java
index dcfd6d8..7e979b7 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java
@@ -32,6 +32,7 @@
private Bitmap mThumbnail; // generated by Activity.onCreateThumbnail()
private Drawable mIcon; // application package icon
private CharSequence mLabel; // application package label
+ private boolean mLoaded;
public TaskDescription(int _taskId, int _persistentTaskId,
ResolveInfo _resolveInfo, Intent _intent,
@@ -45,6 +46,28 @@
packageName = _packageName;
}
+ public TaskDescription() {
+ resolveInfo = null;
+ intent = null;
+ taskId = -1;
+ persistentTaskId = -1;
+
+ description = null;
+ packageName = null;
+ }
+
+ public void setLoaded(boolean loaded) {
+ mLoaded = loaded;
+ }
+
+ public boolean isLoaded() {
+ return mLoaded;
+ }
+
+ public boolean isNull() {
+ return resolveInfo == null;
+ }
+
// mark all these as locked?
public CharSequence getLabel() {
return mLabel;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 5a1e3f4..b3cef90 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -393,7 +393,7 @@
}
lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
lp.setTitle("RecentsPanel");
- lp.windowAnimations = R.style.Animation_RecentPanel;
+ lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications;
lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
return lp;
@@ -403,11 +403,13 @@
// Recents Panel
boolean visible = false;
ArrayList<TaskDescription> recentTasksList = null;
+ boolean firstScreenful = false;
if (mRecentsPanel != null) {
visible = mRecentsPanel.isShowing();
WindowManagerImpl.getDefault().removeView(mRecentsPanel);
if (visible) {
recentTasksList = mRecentsPanel.getRecentTasksList();
+ firstScreenful = mRecentsPanel.getFirstScreenful();
}
}
@@ -425,7 +427,7 @@
WindowManagerImpl.getDefault().addView(mRecentsPanel, lp);
mRecentsPanel.setBar(this);
if (visible) {
- mRecentsPanel.show(true, false, recentTasksList);
+ mRecentsPanel.show(true, false, recentTasksList, firstScreenful);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index d787e10..c59290c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -88,6 +88,7 @@
int mLastSignalLevel;
boolean mShowPhoneRSSIForData = false;
boolean mShowAtLeastThreeGees = false;
+ boolean mAlwaysShowCdmaRssi = false;
String mContentDescriptionPhoneSignal;
String mContentDescriptionWifi;
@@ -156,7 +157,7 @@
IBatteryStats mBatteryStats;
public interface SignalCluster {
- void setWifiIndicators(boolean visible, int strengthIcon, int activityIcon,
+ void setWifiIndicators(boolean visible, int strengthIcon, int activityIcon,
String contentDescription);
void setMobileDataIndicators(boolean visible, int strengthIcon, int activityIcon,
int typeIcon, String contentDescription, String typeContentDescription);
@@ -176,6 +177,8 @@
mShowPhoneRSSIForData = res.getBoolean(R.bool.config_showPhoneRSSIForData);
mShowAtLeastThreeGees = res.getBoolean(R.bool.config_showMin3G);
+ mAlwaysShowCdmaRssi = res.getBoolean(
+ com.android.internal.R.bool.config_alwaysUseCdmaRssi);
// set up the default wifi icon, used when no radios have ever appeared
updateWifiIcons();
@@ -287,7 +290,7 @@
// wimax is special
cluster.setMobileDataIndicators(
true,
- mWimaxIconId,
+ mAlwaysShowCdmaRssi ? mPhoneSignalIconId : mWimaxIconId,
mMobileActivityIconId,
mDataTypeIconId,
mContentDescriptionWimax,
@@ -351,7 +354,7 @@
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
if (DEBUG) {
- Slog.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength +
+ Slog.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength +
((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel())));
}
mSignalStrength = signalStrength;
@@ -469,7 +472,15 @@
} else {
int iconLevel;
int[] iconList;
- mLastSignalLevel = iconLevel = mSignalStrength.getLevel();
+ if (isCdma() && mAlwaysShowCdmaRssi) {
+ mLastSignalLevel = iconLevel = mSignalStrength.getCdmaLevel();
+ if(DEBUG) Slog.d(TAG, "mAlwaysShowCdmaRssi=" + mAlwaysShowCdmaRssi
+ + " set to cdmaLevel=" + mSignalStrength.getCdmaLevel()
+ + " instead of level=" + mSignalStrength.getLevel());
+ } else {
+ mLastSignalLevel = iconLevel = mSignalStrength.getLevel();
+ }
+
if (isCdma()) {
if (isCdmaEri()) {
iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition];
@@ -487,7 +498,6 @@
mPhoneSignalIconId = iconList[iconLevel];
mContentDescriptionPhoneSignal = mContext.getString(
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[iconLevel]);
-
mDataSignalIconId = TelephonyIcons.DATA_SIGNAL_STRENGTH[mInetCondition][iconLevel];
}
}
@@ -914,7 +924,7 @@
mobileLabel = "";
}
} else {
- mobileLabel
+ mobileLabel
= context.getString(R.string.status_bar_settings_signal_meter_disconnected);
}
@@ -1190,7 +1200,7 @@
v.setText(wifiLabel);
}
}
-
+
// mobile label
N = mMobileLabelViews.size();
for (int i=0; i<N; i++) {
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index deeb2de..157405a 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -6,7 +6,8 @@
AudioFlinger.cpp \
AudioMixer.cpp.arm \
AudioResampler.cpp.arm \
- AudioPolicyService.cpp
+ AudioPolicyService.cpp \
+ ServiceUtilities.cpp
# AudioResamplerSinc.cpp.arm
# AudioResamplerCubic.cpp.arm
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index bbc9196..0248687 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1,4 +1,4 @@
-/* //device/include/server/AudioFlinger/AudioFlinger.cpp
+/*
**
** Copyright 2007, The Android Open Source Project
**
@@ -48,6 +48,7 @@
#include "AudioMixer.h"
#include "AudioFlinger.h"
+#include "ServiceUtilities.h"
#include <media/EffectsFactoryApi.h>
#include <audio_effects/effect_visualizer.h>
@@ -101,20 +102,6 @@
// ----------------------------------------------------------------------------
-static bool recordingAllowed() {
- if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
- bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO"));
- if (!ok) ALOGE("Request requires android.permission.RECORD_AUDIO");
- return ok;
-}
-
-static bool settingsAllowed() {
- if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
- bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
- if (!ok) ALOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
- return ok;
-}
-
// To collect the amplifier usage
static void addBatteryData(uint32_t params) {
sp<IMediaPlayerService> service = IMediaDeathNotifier::getMediaPlayerService();
@@ -321,7 +308,7 @@
status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
{
- if (!checkCallingPermission(String16("android.permission.DUMP"))) {
+ if (!dumpAllowed()) {
dumpPermissionDenial(fd, args);
} else {
// get state of hardware lock
@@ -553,7 +540,7 @@
Mutex::Autolock _l(mLock);
mMasterVolume = value;
- for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++)
mPlaybackThreads.valueAt(i)->setMasterVolume(value);
return NO_ERROR;
@@ -585,7 +572,7 @@
if (NO_ERROR == ret) {
Mutex::Autolock _l(mLock);
mMode = mode;
- for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++)
mPlaybackThreads.valueAt(i)->setMode(mode);
}
@@ -634,8 +621,9 @@
}
Mutex::Autolock _l(mLock);
+ // This is an optimization, so PlaybackThread doesn't have to look at the one from AudioFlinger
mMasterMute = muted;
- for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++)
mPlaybackThreads.valueAt(i)->setMasterMute(muted);
return NO_ERROR;
@@ -678,7 +666,7 @@
mStreamTypes[stream].volume = value;
if (thread == NULL) {
- for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
}
} else {
@@ -724,7 +712,7 @@
}
volume = thread->streamVolume(stream);
} else {
- volume = mStreamTypes[stream].volume;
+ volume = streamVolume_l(stream);
}
return volume;
@@ -736,7 +724,8 @@
return true;
}
- return mStreamTypes[stream].mute;
+ AutoMutex lock(mLock);
+ return streamMute_l(stream);
}
status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
@@ -941,7 +930,7 @@
{
Mutex::Autolock _l(mLock);
- int index = mNotificationClients.indexOfKey(pid);
+ ssize_t index = mNotificationClients.indexOfKey(pid);
if (index >= 0) {
sp <NotificationClient> client = mNotificationClients.valueFor(pid);
ALOGV("removeNotificationClient() %p, pid %d", client.get(), pid);
@@ -949,9 +938,9 @@
}
ALOGV("%d died, releasing its sessions", pid);
- int num = mAudioSessionRefs.size();
+ size_t num = mAudioSessionRefs.size();
bool removed = false;
- for (int i = 0; i< num; i++) {
+ for (size_t i = 0; i< num; ) {
AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
ALOGV(" pid %d @ %d", ref->pid, i);
if (ref->pid == pid) {
@@ -959,8 +948,9 @@
mAudioSessionRefs.removeAt(i);
delete ref;
removed = true;
- i--;
num--;
+ } else {
+ i++;
}
}
if (removed) {
@@ -1251,7 +1241,7 @@
void AudioFlinger::ThreadBase::checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain)
{
- int index = mSuspendedSessions.indexOfKey(chain->sessionId());
+ ssize_t index = mSuspendedSessions.indexOfKey(chain->sessionId());
if (index < 0) {
return;
}
@@ -1277,7 +1267,7 @@
bool suspend,
int sessionId)
{
- int index = mSuspendedSessions.indexOfKey(sessionId);
+ ssize_t index = mSuspendedSessions.indexOfKey(sessionId);
KeyedVector <int, sp<SuspendedSessionDesc> > sessionEffects;
@@ -1388,11 +1378,13 @@
// There is no AUDIO_STREAM_MIN, and ++ operator does not compile
for (audio_stream_type_t stream = (audio_stream_type_t) 0; stream < AUDIO_STREAM_CNT;
stream = (audio_stream_type_t) (stream + 1)) {
- mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream);
- mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream);
+ mStreamTypes[stream].volume = mAudioFlinger->streamVolume_l(stream);
+ mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream);
// initialized by stream_type_t default constructor
// mStreamTypes[stream].valid = true;
}
+ // mStreamTypes[AUDIO_STREAM_CNT] exists but isn't explicitly initialized here,
+ // because mAudioFlinger doesn't have one to copy from
}
AudioFlinger::PlaybackThread::~PlaybackThread()
@@ -1586,40 +1578,36 @@
}
}
-status_t AudioFlinger::PlaybackThread::setMasterVolume(float value)
+void AudioFlinger::PlaybackThread::setMasterVolume(float value)
{
+ Mutex::Autolock _l(mLock);
mMasterVolume = value;
- return NO_ERROR;
}
-status_t AudioFlinger::PlaybackThread::setMasterMute(bool muted)
+void AudioFlinger::PlaybackThread::setMasterMute(bool muted)
{
- mMasterMute = muted;
- return NO_ERROR;
+ Mutex::Autolock _l(mLock);
+ setMasterMute_l(muted);
}
-status_t AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
+void AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
{
+ Mutex::Autolock _l(mLock);
mStreamTypes[stream].volume = value;
- return NO_ERROR;
}
-status_t AudioFlinger::PlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted)
+void AudioFlinger::PlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted)
{
+ Mutex::Autolock _l(mLock);
mStreamTypes[stream].mute = muted;
- return NO_ERROR;
}
float AudioFlinger::PlaybackThread::streamVolume(audio_stream_type_t stream) const
{
+ Mutex::Autolock _l(mLock);
return mStreamTypes[stream].volume;
}
-bool AudioFlinger::PlaybackThread::streamMute(audio_stream_type_t stream) const
-{
- return mStreamTypes[stream].mute;
-}
-
// addTrack_l() must be called with ThreadBase::mLock held
status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
{
@@ -1949,7 +1937,7 @@
property_get("ro.audio.silent", value, "0");
if (atoi(value)) {
ALOGD("Silence is golden");
- setMasterMute(true);
+ setMasterMute_l(true);
}
}
@@ -2650,7 +2638,7 @@
property_get("ro.audio.silent", value, "0");
if (atoi(value)) {
ALOGD("Silence is golden");
- setMasterMute(true);
+ setMasterMute_l(true);
}
}
@@ -3046,7 +3034,7 @@
property_get("ro.audio.silent", value, "0");
if (atoi(value)) {
ALOGD("Silence is golden");
- setMasterMute(true);
+ setMasterMute_l(true);
}
}
@@ -3134,6 +3122,7 @@
void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
{
+ // FIXME explain this formula
int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread,
this,
@@ -3405,7 +3394,7 @@
{
// NOTE: destroyTrack_l() can remove a strong reference to this Track
// by removing it from mTracks vector, so there is a risk that this Tracks's
- // desctructor is called. As the destructor needs to lock mLock,
+ // destructor is called. As the destructor needs to lock mLock,
// we must acquire a strong reference on this Track before locking mLock
// here so that the destructor is called only when exiting this function.
// On the other hand, as long as Track::destroy() is only called by
@@ -3436,7 +3425,7 @@
uint32_t vlr = mCblk->getVolumeLR();
snprintf(buffer, size, " %05d %05d %03u %03u 0x%08x %05u %04u %1d %1d %1d %05u %05u %05u 0x%08x 0x%08x 0x%08x 0x%08x\n",
mName - AudioMixer::TRACK0,
- (mClient == 0) ? getpid() : mClient->pid(),
+ (mClient == 0) ? getpid_cached : mClient->pid(),
mStreamType,
mFormat,
mChannelMask,
@@ -3507,11 +3496,11 @@
return false;
}
-status_t AudioFlinger::PlaybackThread::Track::start()
+status_t AudioFlinger::PlaybackThread::Track::start(pid_t tid)
{
status_t status = NO_ERROR;
- ALOGV("start(%d), calling pid %d session %d",
- mName, IPCThreadState::self()->getCallingPid(), mSessionId);
+ ALOGV("start(%d), calling pid %d session %d tid %d",
+ mName, IPCThreadState::self()->getCallingPid(), mSessionId, tid);
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
Mutex::Autolock _l(thread->mLock);
@@ -3730,12 +3719,12 @@
return NOT_ENOUGH_DATA;
}
-status_t AudioFlinger::RecordThread::RecordTrack::start()
+status_t AudioFlinger::RecordThread::RecordTrack::start(pid_t tid)
{
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
RecordThread *recordThread = (RecordThread *)thread.get();
- return recordThread->start(this);
+ return recordThread->start(this, tid);
} else {
return BAD_VALUE;
}
@@ -3757,7 +3746,7 @@
void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
{
snprintf(buffer, size, " %05d %03u 0x%08x %05d %04u %01d %05u %08x %08x\n",
- (mClient == 0) ? getpid() : mClient->pid(),
+ (mClient == 0) ? getpid_cached : mClient->pid(),
mFormat,
mChannelMask,
mSessionId,
@@ -3802,9 +3791,9 @@
clearBufferQueue();
}
-status_t AudioFlinger::PlaybackThread::OutputTrack::start()
+status_t AudioFlinger::PlaybackThread::OutputTrack::start(pid_t tid)
{
- status_t status = Track::start();
+ status_t status = Track::start(tid);
if (status != NO_ERROR) {
return status;
}
@@ -3834,7 +3823,7 @@
uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
if (!mActive && frames != 0) {
- start();
+ start(0);
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
MixerThread *mixerThread = (MixerThread *)thread.get();
@@ -4011,6 +4000,7 @@
AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
: RefBase(),
mAudioFlinger(audioFlinger),
+ // FIXME should be a "k" constant not hard-coded, in .h or ro. property, see 4 lines below
mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
mPid(pid)
{
@@ -4069,8 +4059,8 @@
return mTrack->getCblk();
}
-status_t AudioFlinger::TrackHandle::start() {
- return mTrack->start();
+status_t AudioFlinger::TrackHandle::start(pid_t tid) {
+ return mTrack->start(tid);
}
void AudioFlinger::TrackHandle::stop() {
@@ -4192,9 +4182,9 @@
return mRecordTrack->getCblk();
}
-status_t AudioFlinger::RecordHandle::start() {
+status_t AudioFlinger::RecordHandle::start(pid_t tid) {
ALOGV("RecordHandle::start()");
- return mRecordTrack->start();
+ return mRecordTrack->start(tid);
}
void AudioFlinger::RecordHandle::stop() {
@@ -4486,9 +4476,9 @@
return track;
}
-status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
+status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack, pid_t tid)
{
- ALOGV("RecordThread::start");
+ ALOGV("RecordThread::start tid=%d", tid);
sp <ThreadBase> strongMe = this;
status_t status = NO_ERROR;
{
@@ -4672,7 +4662,7 @@
}
if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
// do not accept frame count changes if tracks are open as the track buffer
- // size depends on frame count and correct behavior would not be garantied
+ // size depends on frame count and correct behavior would not be guaranteed
// if frame count is changed after track creation
if (mActiveTrack != 0) {
status = INVALID_OPERATION;
@@ -5189,8 +5179,8 @@
Mutex::Autolock _l(mLock);
pid_t caller = IPCThreadState::self()->getCallingPid();
ALOGV("acquiring %d from %d", audioSession, caller);
- int num = mAudioSessionRefs.size();
- for (int i = 0; i< num; i++) {
+ size_t num = mAudioSessionRefs.size();
+ for (size_t i = 0; i< num; i++) {
AudioSessionRef *ref = mAudioSessionRefs.editItemAt(i);
if (ref->sessionid == audioSession && ref->pid == caller) {
ref->cnt++;
@@ -5207,8 +5197,8 @@
Mutex::Autolock _l(mLock);
pid_t caller = IPCThreadState::self()->getCallingPid();
ALOGV("releasing %d from %d", audioSession, caller);
- int num = mAudioSessionRefs.size();
- for (int i = 0; i< num; i++) {
+ size_t num = mAudioSessionRefs.size();
+ for (size_t i = 0; i< num; i++) {
AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
if (ref->sessionid == audioSession && ref->pid == caller) {
ref->cnt--;
@@ -5404,7 +5394,7 @@
// Session AUDIO_SESSION_OUTPUT_STAGE is reserved for output stage effects
// that can only be created by audio policy manager (running in same process)
- if (sessionId == AUDIO_SESSION_OUTPUT_STAGE && getpid() != pid) {
+ if (sessionId == AUDIO_SESSION_OUTPUT_STAGE && getpid_cached != pid) {
lStatus = PERMISSION_DENIED;
goto Exit;
}
@@ -6120,7 +6110,6 @@
status_t status;
Mutex::Autolock _l(mLock);
- // First handle in mHandles has highest priority and controls the effect module
int priority = handle->priority();
size_t size = mHandles.size();
sp<EffectHandle> h;
@@ -7022,7 +7011,7 @@
bool locked = mCblk != NULL && tryLock(mCblk->lock);
snprintf(buffer, size, "\t\t\t%05d %05d %01u %01u %05u %05u\n",
- (mClient == 0) ? getpid() : mClient->pid(),
+ (mClient == 0) ? getpid_cached : mClient->pid(),
mPriority,
mHasControl,
!locked,
@@ -7190,12 +7179,12 @@
// Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
// already present
- int size = (int)mEffects.size();
- int idx_insert = size;
- int idx_insert_first = -1;
- int idx_insert_last = -1;
+ size_t size = mEffects.size();
+ size_t idx_insert = size;
+ ssize_t idx_insert_first = -1;
+ ssize_t idx_insert_last = -1;
- for (int i = 0; i < size; i++) {
+ for (size_t i = 0; i < size; i++) {
effect_descriptor_t d = mEffects[i]->desc();
uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
@@ -7264,11 +7253,10 @@
size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
{
Mutex::Autolock _l(mLock);
- int size = (int)mEffects.size();
- int i;
+ size_t size = mEffects.size();
uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
- for (i = 0; i < size; i++) {
+ for (size_t i = 0; i < size; i++) {
if (effect == mEffects[i]) {
// calling stop here will remove pre-processing effect from the audio HAL.
// This is safe as we hold the EffectChain mutex which guarantees that we are not in
@@ -7415,7 +7403,7 @@
sp<SuspendedEffectDesc> desc;
// use effect type UUID timelow as key as there is no real risk of identical
// timeLow fields among effect type UUIDs.
- int index = mSuspendedEffects.indexOfKey(type->timeLow);
+ ssize_t index = mSuspendedEffects.indexOfKey(type->timeLow);
if (suspend) {
if (index >= 0) {
desc = mSuspendedEffects.valueAt(index);
@@ -7465,7 +7453,7 @@
{
sp<SuspendedEffectDesc> desc;
- int index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
+ ssize_t index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
if (suspend) {
if (index >= 0) {
desc = mSuspendedEffects.valueAt(index);
@@ -7547,7 +7535,7 @@
void AudioFlinger::EffectChain::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
bool enabled)
{
- int index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
+ ssize_t index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
if (enabled) {
if (index < 0) {
// if the effect is not suspend check if all effects are suspended
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index fdcd916..aa0b8f8 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -1,4 +1,4 @@
-/* //device/include/server/AudioFlinger/AudioFlinger.h
+/*
**
** Copyright 2007, The Android Open Source Project
**
@@ -290,6 +290,8 @@
enum track_state {
IDLE,
TERMINATED,
+ // These are order-sensitive; do not change order without reviewing the impact.
+ // In particular there are assumptions about > STOPPED.
STOPPED,
RESUMING,
ACTIVE,
@@ -314,7 +316,7 @@
int sessionId);
virtual ~TrackBase();
- virtual status_t start() = 0;
+ virtual status_t start(pid_t tid) = 0;
virtual void stop() = 0;
sp<IMemory> getCblk() const { return mCblkMemory; }
audio_track_cblk_t* cblk() const { return mCblk; }
@@ -586,7 +588,7 @@
virtual ~Track();
void dump(char* buffer, size_t size);
- virtual status_t start();
+ virtual status_t start(pid_t tid);
virtual void stop();
void pause();
@@ -668,7 +670,7 @@
int frameCount);
virtual ~OutputTrack();
- virtual status_t start();
+ virtual status_t start(pid_t tid);
virtual void stop();
bool write(int16_t* data, uint32_t frames);
bool bufferQueueEmpty() const { return (mBufferQueue.size() == 0) ? true : false; }
@@ -707,17 +709,13 @@
virtual uint32_t latency() const;
- virtual status_t setMasterVolume(float value);
- virtual status_t setMasterMute(bool muted);
+ void setMasterVolume(float value);
+ void setMasterMute(bool muted);
- virtual float masterVolume() const { return mMasterVolume; }
- virtual bool masterMute() const { return mMasterMute; }
+ void setStreamVolume(audio_stream_type_t stream, float value);
+ void setStreamMute(audio_stream_type_t stream, bool muted);
- virtual status_t setStreamVolume(audio_stream_type_t stream, float value);
- virtual status_t setStreamMute(audio_stream_type_t stream, bool muted);
-
- virtual float streamVolume(audio_stream_type_t stream) const;
- virtual bool streamMute(audio_stream_type_t stream) const;
+ float streamVolume(audio_stream_type_t stream) const;
sp<Track> createTrack_l(
const sp<AudioFlinger::Client>& client,
@@ -760,7 +758,11 @@
int mSuspended;
int mBytesWritten;
private:
+ // mMasterMute is in both PlaybackThread and in AudioFlinger. When a
+ // PlaybackThread needs to find out if master-muted, it checks it's local
+ // copy rather than the one in AudioFlinger. This optimization saves a lock.
bool mMasterMute;
+ void setMasterMute_l(bool muted) { mMasterMute = muted; }
protected:
SortedVector< wp<Track> > mActiveTracks;
@@ -853,6 +855,8 @@
private:
void applyVolume(uint16_t leftVol, uint16_t rightVol, bool ramp);
+ // volumes last sent to audio HAL with stream->set_volume()
+ // FIXME use standard representation and names
float mLeftVolFloat;
float mRightVolFloat;
uint16_t mLeftVolShort;
@@ -884,7 +888,11 @@
PlaybackThread *checkPlaybackThread_l(audio_io_handle_t output) const;
MixerThread *checkMixerThread_l(audio_io_handle_t output) const;
RecordThread *checkRecordThread_l(audio_io_handle_t input) const;
- float streamVolumeInternal(audio_stream_type_t stream) const
+ // no range check, AudioFlinger::mLock held
+ bool streamMute_l(audio_stream_type_t stream) const
+ { return mStreamTypes[stream].mute; }
+ // no range check, doesn't check per-thread stream volume, AudioFlinger::mLock held
+ float streamVolume_l(audio_stream_type_t stream) const
{ return mStreamTypes[stream].volume; }
void audioConfigChanged_l(int event, audio_io_handle_t ioHandle, void *param2);
@@ -900,12 +908,13 @@
friend class AudioBuffer;
+ // server side of the client's IAudioTrack
class TrackHandle : public android::BnAudioTrack {
public:
TrackHandle(const sp<PlaybackThread::Track>& track);
virtual ~TrackHandle();
virtual sp<IMemory> getCblk() const;
- virtual status_t start();
+ virtual status_t start(pid_t tid);
virtual void stop();
virtual void flush();
virtual void mute(bool);
@@ -943,7 +952,7 @@
int sessionId);
virtual ~RecordTrack();
- virtual status_t start();
+ virtual status_t start(pid_t tid);
virtual void stop();
bool overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; }
@@ -988,6 +997,7 @@
status_t *status);
status_t start(RecordTrack* recordTrack);
+ status_t start(RecordTrack* recordTrack, pid_t tid);
void stop(RecordTrack* recordTrack);
status_t dump(int fd, const Vector<String16>& args);
AudioStreamIn* getInput() const;
@@ -1023,12 +1033,13 @@
ssize_t mBytesRead;
};
+ // server side of the client's IAudioRecord
class RecordHandle : public android::BnAudioRecord {
public:
RecordHandle(const sp<RecordThread::RecordTrack>& recordTrack);
virtual ~RecordHandle();
virtual sp<IMemory> getCblk() const;
- virtual status_t start();
+ virtual status_t start(pid_t tid);
virtual void stop();
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
@@ -1151,6 +1162,7 @@
status_t mStatus; // initialization status
effect_state mState; // current activation state
Vector< wp<EffectHandle> > mHandles; // list of client handles
+ // First handle in mHandles has highest priority and controls the effect module
uint32_t mMaxDisableWaitCnt; // maximum grace period before forcing an effect off after
// sending disable command.
uint32_t mDisableWaitCnt; // current process() calls count during disable period.
@@ -1376,6 +1388,7 @@
hwDev(dev), stream(in) {}
};
+ // for mAudioSessionRefs only
struct AudioSessionRef {
// FIXME rename parameter names when fields get "m" prefix
AudioSessionRef(int sessionid_, pid_t pid_) :
@@ -1431,10 +1444,11 @@
DefaultKeyedVector< audio_io_handle_t, sp<RecordThread> > mRecordThreads;
DefaultKeyedVector< pid_t, sp<NotificationClient> > mNotificationClients;
- volatile int32_t mNextUniqueId;
+ volatile int32_t mNextUniqueId; // updated by android_atomic_inc
audio_mode_t mMode;
bool mBtNrecIsOff;
+ // protected by mLock
Vector<AudioSessionRef*> mAudioSessionRefs;
float masterVolume_l() const { return mMasterVolume; }
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index 191520a..cb7678b 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
@@ -1,4 +1,4 @@
-/* //device/include/server/AudioFlinger/AudioMixer.cpp
+/*
**
** Copyright 2007, The Android Open Source Project
**
@@ -961,7 +961,12 @@
// one track, 16 bits stereo without resampling is the most common case
void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state)
{
+ // This method is only called when state->enabledTracks has exactly
+ // one bit set. The asserts below would verify this, but are commented out
+ // since the whole point of this method is to optimize performance.
+ //assert(0 != state->enabledTracks);
const int i = 31 - __builtin_clz(state->enabledTracks);
+ //assert((1 << i) == state->enabledTracks);
const track_t& t = state->tracks[i];
AudioBufferProvider::Buffer& b(t.buffer);
diff --git a/services/audioflinger/AudioMixer.h b/services/audioflinger/AudioMixer.h
index c709686..c956918 100644
--- a/services/audioflinger/AudioMixer.h
+++ b/services/audioflinger/AudioMixer.h
@@ -1,4 +1,4 @@
-/* //device/include/server/AudioFlinger/AudioMixer.h
+/*
**
** Copyright 2007, The Android Open Source Project
**
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index f8b430e..041b5a8 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -30,6 +30,7 @@
#include <utils/String16.h>
#include <utils/threads.h>
#include "AudioPolicyService.h"
+#include "ServiceUtilities.h"
#include <cutils/properties.h>
#include <hardware_legacy/power.h>
#include <media/AudioEffect.h>
@@ -49,13 +50,6 @@
static const int kDumpLockRetries = 50;
static const int kDumpLockSleepUs = 20000;
-static bool checkPermission() {
- if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
- bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
- if (!ok) ALOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
- return ok;
-}
-
namespace {
extern struct audio_policy_service_ops aps_ops;
};
@@ -157,7 +151,7 @@
if (mpAudioPolicy == NULL) {
return NO_INIT;
}
- if (!checkPermission()) {
+ if (!settingsAllowed()) {
return PERMISSION_DENIED;
}
if (!audio_is_output_device(device) && !audio_is_input_device(device)) {
@@ -190,7 +184,7 @@
if (mpAudioPolicy == NULL) {
return NO_INIT;
}
- if (!checkPermission()) {
+ if (!settingsAllowed()) {
return PERMISSION_DENIED;
}
if (uint32_t(state) >= AUDIO_MODE_CNT) {
@@ -213,7 +207,7 @@
if (mpAudioPolicy == NULL) {
return NO_INIT;
}
- if (!checkPermission()) {
+ if (!settingsAllowed()) {
return PERMISSION_DENIED;
}
if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) {
@@ -388,7 +382,7 @@
if (mpAudioPolicy == NULL) {
return NO_INIT;
}
- if (!checkPermission()) {
+ if (!settingsAllowed()) {
return PERMISSION_DENIED;
}
if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
@@ -405,7 +399,7 @@
if (mpAudioPolicy == NULL) {
return NO_INIT;
}
- if (!checkPermission()) {
+ if (!settingsAllowed()) {
return PERMISSION_DENIED;
}
if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
@@ -578,7 +572,7 @@
status_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
{
- if (!checkCallingPermission(String16("android.permission.DUMP"))) {
+ if (!dumpAllowed()) {
dumpPermissionDenial(fd);
} else {
bool locked = tryLock(mLock);
@@ -774,7 +768,7 @@
snprintf(buffer, SIZE, "- Commands:\n");
result = String8(buffer);
result.append(" Command Time Wait pParam\n");
- for (int i = 0; i < (int)mAudioCommands.size(); i++) {
+ for (size_t i = 0; i < mAudioCommands.size(); i++) {
mAudioCommands[i]->dump(buffer, SIZE);
result.append(buffer);
}
@@ -908,7 +902,7 @@
// insertCommand_l() must be called with mLock held
void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
{
- ssize_t i;
+ ssize_t i; // not size_t because i will count down to -1
Vector <AudioCommand *> removedCommands;
command->mTime = systemTime() + milliseconds(delayMs);
diff --git a/services/audioflinger/ServiceUtilities.cpp b/services/audioflinger/ServiceUtilities.cpp
new file mode 100644
index 0000000..6a58852
--- /dev/null
+++ b/services/audioflinger/ServiceUtilities.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/PermissionCache.h>
+#include "ServiceUtilities.h"
+
+namespace android {
+
+// This optimization assumes mediaserver process doesn't fork, which it doesn't
+const pid_t getpid_cached = getpid();
+
+bool recordingAllowed() {
+ if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true;
+ static const String16 sRecordAudio("android.permission.RECORD_AUDIO");
+ // don't use PermissionCache; this is not a system permission
+ bool ok = checkCallingPermission(sRecordAudio);
+ if (!ok) ALOGE("Request requires android.permission.RECORD_AUDIO");
+ return ok;
+}
+
+bool settingsAllowed() {
+ if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true;
+ static const String16 sAudioSettings("android.permission.MODIFY_AUDIO_SETTINGS");
+ // don't use PermissionCache; this is not a system permission
+ bool ok = checkCallingPermission(sAudioSettings);
+ if (!ok) ALOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
+ return ok;
+}
+
+bool dumpAllowed() {
+ // don't optimize for same pid, since mediaserver never dumps itself
+ static const String16 sDump("android.permission.DUMP");
+ // OK to use PermissionCache; this is a system permission
+ bool ok = PermissionCache::checkCallingPermission(sDump);
+ // convention is for caller to dump an error message to fd instead of logging here
+ //if (!ok) ALOGE("Request requires android.permission.DUMP");
+ return ok;
+}
+
+} // namespace android
diff --git a/services/audioflinger/ServiceUtilities.h b/services/audioflinger/ServiceUtilities.h
new file mode 100644
index 0000000..f77ec5bc
--- /dev/null
+++ b/services/audioflinger/ServiceUtilities.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h>
+
+namespace android {
+
+extern const pid_t getpid_cached;
+
+bool recordingAllowed();
+bool settingsAllowed();
+bool dumpAllowed();
+
+}
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 34a8a02..b3eceb1 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -768,7 +768,9 @@
long identity = Binder.clearCallingIdentity();
try {
r.statusBarKey = mStatusBar.addNotification(n);
- mAttentionLight.pulse();
+ if ((n.notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0) {
+ mAttentionLight.pulse();
+ }
}
finally {
Binder.restoreCallingIdentity(identity);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 7bf26cc..9d5caae 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -292,813 +292,12 @@
final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
= new ArrayList<PendingActivityLaunch>();
- /**
- * BROADCASTS
- *
- * We keep two broadcast queues and associated bookkeeping, one for those at
- * foreground priority, and one for normal (background-priority) broadcasts.
- */
- public class BroadcastQueue {
- static final String TAG = "BroadcastQueue";
- static final int MAX_BROADCAST_HISTORY = 25;
-
- /**
- * Recognizable moniker for this queue
- */
- String mQueueName;
-
- /**
- * Timeout period for this queue's broadcasts
- */
- long mTimeoutPeriod;
-
- /**
- * Lists of all active broadcasts that are to be executed immediately
- * (without waiting for another broadcast to finish). Currently this only
- * contains broadcasts to registered receivers, to avoid spinning up
- * a bunch of processes to execute IntentReceiver components. Background-
- * and foreground-priority broadcasts are queued separately.
- */
- final ArrayList<BroadcastRecord> mParallelBroadcasts
- = new ArrayList<BroadcastRecord>();
- /**
- * List of all active broadcasts that are to be executed one at a time.
- * The object at the top of the list is the currently activity broadcasts;
- * those after it are waiting for the top to finish. As with parallel
- * broadcasts, separate background- and foreground-priority queues are
- * maintained.
- */
- final ArrayList<BroadcastRecord> mOrderedBroadcasts
- = new ArrayList<BroadcastRecord>();
-
- /**
- * Historical data of past broadcasts, for debugging.
- */
- final BroadcastRecord[] mBroadcastHistory
- = new BroadcastRecord[MAX_BROADCAST_HISTORY];
-
- /**
- * Set when we current have a BROADCAST_INTENT_MSG in flight.
- */
- boolean mBroadcastsScheduled = false;
-
- /**
- * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
- */
- boolean mPendingBroadcastTimeoutMessage;
-
- /**
- * Intent broadcasts that we have tried to start, but are
- * waiting for the application's process to be created. We only
- * need one per scheduling class (instead of a list) because we always
- * process broadcasts one at a time, so no others can be started while
- * waiting for this one.
- */
- BroadcastRecord mPendingBroadcast = null;
-
- /**
- * The receiver index that is pending, to restart the broadcast if needed.
- */
- int mPendingBroadcastRecvIndex;
-
- BroadcastQueue(String name, long timeoutPeriod) {
- mQueueName = name;
- mTimeoutPeriod = timeoutPeriod;
- }
-
- public boolean isPendingBroadcastProcessLocked(int pid) {
- return mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid;
- }
-
- public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
- mParallelBroadcasts.add(r);
- }
-
- public void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
- mOrderedBroadcasts.add(r);
- }
-
- public final boolean replaceParallelBroadcastLocked(BroadcastRecord r) {
- for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
- if (r.intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
- if (DEBUG_BROADCAST) Slog.v(TAG,
- "***** DROPPING PARALLEL ["
- + mQueueName + "]: " + r.intent);
- mParallelBroadcasts.set(i, r);
- return true;
- }
- }
- return false;
- }
-
- public final boolean replaceOrderedBroadcastLocked(BroadcastRecord r) {
- for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
- if (r.intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
- if (DEBUG_BROADCAST) Slog.v(TAG,
- "***** DROPPING ORDERED ["
- + mQueueName + "]: " + r.intent);
- mOrderedBroadcasts.set(i, r);
- return true;
- }
- }
- return false;
- }
-
- public boolean sendPendingBroadcastsLocked(ProcessRecord app) {
- boolean didSomething = false;
- final BroadcastRecord br = mPendingBroadcast;
- if (br != null && br.curApp.pid == app.pid) {
- try {
- mPendingBroadcast = null;
- processCurBroadcastLocked(br, app);
- didSomething = true;
- } catch (Exception e) {
- Slog.w(TAG, "Exception in new application when starting receiver "
- + br.curComponent.flattenToShortString(), e);
- logBroadcastReceiverDiscardLocked(br);
- finishReceiverLocked(br, br.resultCode, br.resultData,
- br.resultExtras, br.resultAbort, true);
- scheduleBroadcastsLocked();
- // We need to reset the state if we fails to start the receiver.
- br.state = BroadcastRecord.IDLE;
- throw new RuntimeException(e.getMessage());
- }
- }
- return didSomething;
- }
-
- public void skipPendingBroadcastLocked(int pid) {
- final BroadcastRecord br = mPendingBroadcast;
- if (br != null && br.curApp.pid == pid) {
- br.state = BroadcastRecord.IDLE;
- br.nextReceiver = mPendingBroadcastRecvIndex;
- mPendingBroadcast = null;
- scheduleBroadcastsLocked();
- }
- }
-
- public void skipCurrentReceiverLocked(ProcessRecord app) {
- boolean reschedule = false;
- BroadcastRecord r = app.curReceiver;
- if (r != null) {
- // The current broadcast is waiting for this app's receiver
- // to be finished. Looks like that's not going to happen, so
- // let the broadcast continue.
- logBroadcastReceiverDiscardLocked(r);
- finishReceiverLocked(r, r.resultCode, r.resultData,
- r.resultExtras, r.resultAbort, true);
- reschedule = true;
- }
-
- r = mPendingBroadcast;
- if (r != null && r.curApp == app) {
- if (DEBUG_BROADCAST) Slog.v(TAG,
- "[" + mQueueName + "] skip & discard pending app " + r);
- logBroadcastReceiverDiscardLocked(r);
- finishReceiverLocked(r, r.resultCode, r.resultData,
- r.resultExtras, r.resultAbort, true);
- reschedule = true;
- }
- if (reschedule) {
- scheduleBroadcastsLocked();
- }
- }
-
- public void scheduleBroadcastsLocked() {
- if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts ["
- + mQueueName + "]: current="
- + mBroadcastsScheduled);
-
- if (mBroadcastsScheduled) {
- return;
- }
- mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
- mBroadcastsScheduled = true;
- }
-
- public BroadcastRecord getMatchingOrderedReceiver(IBinder receiver) {
- if (mOrderedBroadcasts.size() > 0) {
- final BroadcastRecord r = mOrderedBroadcasts.get(0);
- if (r != null && r.receiver == receiver) {
- return r;
- }
- }
- return null;
- }
-
- public boolean finishReceiverLocked(BroadcastRecord r, int resultCode,
- String resultData, Bundle resultExtras, boolean resultAbort,
- boolean explicit) {
- int state = r.state;
- r.state = BroadcastRecord.IDLE;
- if (state == BroadcastRecord.IDLE) {
- if (explicit) {
- Slog.w(TAG, "finishReceiver [" + mQueueName + "] called but state is IDLE");
- }
- }
- r.receiver = null;
- r.intent.setComponent(null);
- if (r.curApp != null) {
- r.curApp.curReceiver = null;
- }
- if (r.curFilter != null) {
- r.curFilter.receiverList.curBroadcast = null;
- }
- r.curFilter = null;
- r.curApp = null;
- r.curComponent = null;
- r.curReceiver = null;
- mPendingBroadcast = null;
-
- r.resultCode = resultCode;
- r.resultData = resultData;
- r.resultExtras = resultExtras;
- r.resultAbort = resultAbort;
-
- // We will process the next receiver right now if this is finishing
- // an app receiver (which is always asynchronous) or after we have
- // come back from calling a receiver.
- return state == BroadcastRecord.APP_RECEIVE
- || state == BroadcastRecord.CALL_DONE_RECEIVE;
- }
-
- private final void processNextBroadcast(boolean fromMsg) {
- synchronized(ActivityManagerService.this) {
- BroadcastRecord r;
-
- if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast ["
- + mQueueName + "]: "
- + mParallelBroadcasts.size() + " broadcasts, "
- + mOrderedBroadcasts.size() + " ordered broadcasts");
-
- updateCpuStats();
-
- if (fromMsg) {
- mBroadcastsScheduled = false;
- }
-
- // First, deliver any non-serialized broadcasts right away.
- while (mParallelBroadcasts.size() > 0) {
- r = mParallelBroadcasts.remove(0);
- r.dispatchTime = SystemClock.uptimeMillis();
- r.dispatchClockTime = System.currentTimeMillis();
- final int N = r.receivers.size();
- if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast ["
- + mQueueName + "] " + r);
- for (int i=0; i<N; i++) {
- Object target = r.receivers.get(i);
- if (DEBUG_BROADCAST) Slog.v(TAG,
- "Delivering non-ordered on [" + mQueueName + "] to registered "
- + target + ": " + r);
- deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
- }
- addBroadcastToHistoryLocked(r);
- if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast ["
- + mQueueName + "] " + r);
- }
-
- // Now take care of the next serialized one...
-
- // If we are waiting for a process to come up to handle the next
- // broadcast, then do nothing at this point. Just in case, we
- // check that the process we're waiting for still exists.
- if (mPendingBroadcast != null) {
- if (DEBUG_BROADCAST_LIGHT) {
- Slog.v(TAG, "processNextBroadcast ["
- + mQueueName + "]: waiting for "
- + mPendingBroadcast.curApp);
- }
-
- boolean isDead;
- synchronized (mPidsSelfLocked) {
- isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
- }
- if (!isDead) {
- // It's still alive, so keep waiting
- return;
- } else {
- Slog.w(TAG, "pending app ["
- + mQueueName + "]" + mPendingBroadcast.curApp
- + " died before responding to broadcast");
- mPendingBroadcast.state = BroadcastRecord.IDLE;
- mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
- mPendingBroadcast = null;
- }
- }
-
- boolean looped = false;
-
- do {
- if (mOrderedBroadcasts.size() == 0) {
- // No more broadcasts pending, so all done!
- scheduleAppGcsLocked();
- if (looped) {
- // If we had finished the last ordered broadcast, then
- // make sure all processes have correct oom and sched
- // adjustments.
- updateOomAdjLocked();
- }
- return;
- }
- r = mOrderedBroadcasts.get(0);
- boolean forceReceive = false;
-
- // Ensure that even if something goes awry with the timeout
- // detection, we catch "hung" broadcasts here, discard them,
- // and continue to make progress.
- //
- // This is only done if the system is ready so that PRE_BOOT_COMPLETED
- // receivers don't get executed with timeouts. They're intended for
- // one time heavy lifting after system upgrades and can take
- // significant amounts of time.
- int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
- if (mProcessesReady && r.dispatchTime > 0) {
- long now = SystemClock.uptimeMillis();
- if ((numReceivers > 0) &&
- (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
- Slog.w(TAG, "Hung broadcast ["
- + mQueueName + "] discarded after timeout failure:"
- + " now=" + now
- + " dispatchTime=" + r.dispatchTime
- + " startTime=" + r.receiverTime
- + " intent=" + r.intent
- + " numReceivers=" + numReceivers
- + " nextReceiver=" + r.nextReceiver
- + " state=" + r.state);
- broadcastTimeoutLocked(false); // forcibly finish this broadcast
- forceReceive = true;
- r.state = BroadcastRecord.IDLE;
- }
- }
-
- if (r.state != BroadcastRecord.IDLE) {
- if (DEBUG_BROADCAST) Slog.d(TAG,
- "processNextBroadcast("
- + mQueueName + ") called when not idle (state="
- + r.state + ")");
- return;
- }
-
- if (r.receivers == null || r.nextReceiver >= numReceivers
- || r.resultAbort || forceReceive) {
- // No more receivers for this broadcast! Send the final
- // result if requested...
- if (r.resultTo != null) {
- try {
- if (DEBUG_BROADCAST) {
- int seq = r.intent.getIntExtra("seq", -1);
- Slog.i(TAG, "Finishing broadcast ["
- + mQueueName + "] " + r.intent.getAction()
- + " seq=" + seq + " app=" + r.callerApp);
- }
- performReceiveLocked(r.callerApp, r.resultTo,
- new Intent(r.intent), r.resultCode,
- r.resultData, r.resultExtras, false, false);
- // Set this to null so that the reference
- // (local and remote) isnt kept in the mBroadcastHistory.
- r.resultTo = null;
- } catch (RemoteException e) {
- Slog.w(TAG, "Failure ["
- + mQueueName + "] sending broadcast result of "
- + r.intent, e);
- }
- }
-
- if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
- cancelBroadcastTimeoutLocked();
-
- if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
- + r);
-
- // ... and on to the next...
- addBroadcastToHistoryLocked(r);
- mOrderedBroadcasts.remove(0);
- r = null;
- looped = true;
- continue;
- }
- } while (r == null);
-
- // Get the next receiver...
- int recIdx = r.nextReceiver++;
-
- // Keep track of when this receiver started, and make sure there
- // is a timeout message pending to kill it if need be.
- r.receiverTime = SystemClock.uptimeMillis();
- if (recIdx == 0) {
- r.dispatchTime = r.receiverTime;
- r.dispatchClockTime = System.currentTimeMillis();
- if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast ["
- + mQueueName + "] " + r);
- }
- if (! mPendingBroadcastTimeoutMessage) {
- long timeoutTime = r.receiverTime + mTimeoutPeriod;
- if (DEBUG_BROADCAST) Slog.v(TAG,
- "Submitting BROADCAST_TIMEOUT_MSG ["
- + mQueueName + "] for " + r + " at " + timeoutTime);
- setBroadcastTimeoutLocked(timeoutTime);
- }
-
- Object nextReceiver = r.receivers.get(recIdx);
- if (nextReceiver instanceof BroadcastFilter) {
- // Simple case: this is a registered receiver who gets
- // a direct call.
- BroadcastFilter filter = (BroadcastFilter)nextReceiver;
- if (DEBUG_BROADCAST) Slog.v(TAG,
- "Delivering ordered ["
- + mQueueName + "] to registered "
- + filter + ": " + r);
- deliverToRegisteredReceiverLocked(r, filter, r.ordered);
- if (r.receiver == null || !r.ordered) {
- // The receiver has already finished, so schedule to
- // process the next one.
- if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing ["
- + mQueueName + "]: ordered="
- + r.ordered + " receiver=" + r.receiver);
- r.state = BroadcastRecord.IDLE;
- scheduleBroadcastsLocked();
- }
- return;
- }
-
- // Hard case: need to instantiate the receiver, possibly
- // starting its application process to host it.
-
- ResolveInfo info =
- (ResolveInfo)nextReceiver;
-
- boolean skip = false;
- int perm = checkComponentPermission(info.activityInfo.permission,
- r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
- info.activityInfo.exported);
- if (perm != PackageManager.PERMISSION_GRANTED) {
- if (!info.activityInfo.exported) {
- Slog.w(TAG, "Permission Denial: broadcasting "
- + r.intent.toString()
- + " from " + r.callerPackage + " (pid=" + r.callingPid
- + ", uid=" + r.callingUid + ")"
- + " is not exported from uid " + info.activityInfo.applicationInfo.uid
- + " due to receiver " + info.activityInfo.packageName
- + "/" + info.activityInfo.name);
- } else {
- Slog.w(TAG, "Permission Denial: broadcasting "
- + r.intent.toString()
- + " from " + r.callerPackage + " (pid=" + r.callingPid
- + ", uid=" + r.callingUid + ")"
- + " requires " + info.activityInfo.permission
- + " due to receiver " + info.activityInfo.packageName
- + "/" + info.activityInfo.name);
- }
- skip = true;
- }
- if (info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
- r.requiredPermission != null) {
- try {
- perm = AppGlobals.getPackageManager().
- checkPermission(r.requiredPermission,
- info.activityInfo.applicationInfo.packageName);
- } catch (RemoteException e) {
- perm = PackageManager.PERMISSION_DENIED;
- }
- if (perm != PackageManager.PERMISSION_GRANTED) {
- Slog.w(TAG, "Permission Denial: receiving "
- + r.intent + " to "
- + info.activityInfo.applicationInfo.packageName
- + " requires " + r.requiredPermission
- + " due to sender " + r.callerPackage
- + " (uid " + r.callingUid + ")");
- skip = true;
- }
- }
- if (r.curApp != null && r.curApp.crashing) {
- // If the target process is crashing, just skip it.
- if (DEBUG_BROADCAST) Slog.v(TAG,
- "Skipping deliver ordered ["
- + mQueueName + "] " + r + " to " + r.curApp
- + ": process crashing");
- skip = true;
- }
-
- if (skip) {
- if (DEBUG_BROADCAST) Slog.v(TAG,
- "Skipping delivery of ordered ["
- + mQueueName + "] " + r + " for whatever reason");
- r.receiver = null;
- r.curFilter = null;
- r.state = BroadcastRecord.IDLE;
- scheduleBroadcastsLocked();
- return;
- }
-
- r.state = BroadcastRecord.APP_RECEIVE;
- String targetProcess = info.activityInfo.processName;
- r.curComponent = new ComponentName(
- info.activityInfo.applicationInfo.packageName,
- info.activityInfo.name);
- if (r.callingUid != Process.SYSTEM_UID) {
- info.activityInfo = getActivityInfoForUser(info.activityInfo, UserId
- .getUserId(r.callingUid));
- }
- r.curReceiver = info.activityInfo;
- if (DEBUG_MU && r.callingUid > UserId.PER_USER_RANGE) {
- Slog.v(TAG_MU, "Updated broadcast record activity info for secondary user, "
- + info.activityInfo + ", callingUid = " + r.callingUid + ", uid = "
- + info.activityInfo.applicationInfo.uid);
- }
-
- // Broadcast is being executed, its package can't be stopped.
- try {
- AppGlobals.getPackageManager().setPackageStoppedState(
- r.curComponent.getPackageName(), false);
- } catch (RemoteException e) {
- } catch (IllegalArgumentException e) {
- Slog.w(TAG, "Failed trying to unstop package "
- + r.curComponent.getPackageName() + ": " + e);
- }
-
- // Is this receiver's application already running?
- ProcessRecord app = getProcessRecordLocked(targetProcess,
- info.activityInfo.applicationInfo.uid);
- if (app != null && app.thread != null) {
- try {
- app.addPackage(info.activityInfo.packageName);
- processCurBroadcastLocked(r, app);
- return;
- } catch (RemoteException e) {
- Slog.w(TAG, "Exception when sending broadcast to "
- + r.curComponent, e);
- }
-
- // If a dead object exception was thrown -- fall through to
- // restart the application.
- }
-
- // Not running -- get it started, to be executed when the app comes up.
- if (DEBUG_BROADCAST) Slog.v(TAG,
- "Need to start app ["
- + mQueueName + "] " + targetProcess + " for broadcast " + r);
- if ((r.curApp=startProcessLocked(targetProcess,
- info.activityInfo.applicationInfo, true,
- r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
- "broadcast", r.curComponent,
- (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false))
- == null) {
- // Ah, this recipient is unavailable. Finish it if necessary,
- // and mark the broadcast record as ready for the next.
- Slog.w(TAG, "Unable to launch app "
- + info.activityInfo.applicationInfo.packageName + "/"
- + info.activityInfo.applicationInfo.uid + " for broadcast "
- + r.intent + ": process is bad");
- logBroadcastReceiverDiscardLocked(r);
- finishReceiverLocked(r, r.resultCode, r.resultData,
- r.resultExtras, r.resultAbort, true);
- scheduleBroadcastsLocked();
- r.state = BroadcastRecord.IDLE;
- return;
- }
-
- mPendingBroadcast = r;
- mPendingBroadcastRecvIndex = recIdx;
- }
- }
-
- final void setBroadcastTimeoutLocked(long timeoutTime) {
- if (! mPendingBroadcastTimeoutMessage) {
- Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG, this);
- mHandler.sendMessageAtTime(msg, timeoutTime);
- mPendingBroadcastTimeoutMessage = true;
- }
- }
-
- final void cancelBroadcastTimeoutLocked() {
- if (mPendingBroadcastTimeoutMessage) {
- mHandler.removeMessages(BROADCAST_TIMEOUT_MSG, this);
- mPendingBroadcastTimeoutMessage = false;
- }
- }
-
- final void broadcastTimeoutLocked(boolean fromMsg) {
- if (fromMsg) {
- mPendingBroadcastTimeoutMessage = false;
- }
-
- if (mOrderedBroadcasts.size() == 0) {
- return;
- }
-
- long now = SystemClock.uptimeMillis();
- BroadcastRecord r = mOrderedBroadcasts.get(0);
- if (fromMsg) {
- if (mDidDexOpt) {
- // Delay timeouts until dexopt finishes.
- mDidDexOpt = false;
- long timeoutTime = SystemClock.uptimeMillis() + mTimeoutPeriod;
- setBroadcastTimeoutLocked(timeoutTime);
- return;
- }
- if (! mProcessesReady) {
- // Only process broadcast timeouts if the system is ready. That way
- // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
- // to do heavy lifting for system up.
- return;
- }
-
- long timeoutTime = r.receiverTime + mTimeoutPeriod;
- if (timeoutTime > now) {
- // We can observe premature timeouts because we do not cancel and reset the
- // broadcast timeout message after each receiver finishes. Instead, we set up
- // an initial timeout then kick it down the road a little further as needed
- // when it expires.
- if (DEBUG_BROADCAST) Slog.v(TAG,
- "Premature timeout ["
- + mQueueName + "] @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
- + timeoutTime);
- setBroadcastTimeoutLocked(timeoutTime);
- return;
- }
- }
-
- Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
- + ", started " + (now - r.receiverTime) + "ms ago");
- r.receiverTime = now;
- r.anrCount++;
-
- // Current receiver has passed its expiration date.
- if (r.nextReceiver <= 0) {
- Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
- return;
- }
-
- ProcessRecord app = null;
- String anrMessage = null;
-
- Object curReceiver = r.receivers.get(r.nextReceiver-1);
- Slog.w(TAG, "Receiver during timeout: " + curReceiver);
- logBroadcastReceiverDiscardLocked(r);
- if (curReceiver instanceof BroadcastFilter) {
- BroadcastFilter bf = (BroadcastFilter)curReceiver;
- if (bf.receiverList.pid != 0
- && bf.receiverList.pid != MY_PID) {
- synchronized (ActivityManagerService.this.mPidsSelfLocked) {
- app = ActivityManagerService.this.mPidsSelfLocked.get(
- bf.receiverList.pid);
- }
- }
- } else {
- app = r.curApp;
- }
-
- if (app != null) {
- anrMessage = "Broadcast of " + r.intent.toString();
- }
-
- if (mPendingBroadcast == r) {
- mPendingBroadcast = null;
- }
-
- // Move on to the next receiver.
- finishReceiverLocked(r, r.resultCode, r.resultData,
- r.resultExtras, r.resultAbort, true);
- scheduleBroadcastsLocked();
-
- if (anrMessage != null) {
- // Post the ANR to the handler since we do not want to process ANRs while
- // potentially holding our lock.
- mHandler.post(new AppNotResponding(app, anrMessage));
- }
- }
-
- private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
- if (r.callingUid < 0) {
- // This was from a registerReceiver() call; ignore it.
- return;
- }
- System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
- MAX_BROADCAST_HISTORY-1);
- r.finishTime = SystemClock.uptimeMillis();
- mBroadcastHistory[0] = r;
- }
-
- final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
- if (r.nextReceiver > 0) {
- Object curReceiver = r.receivers.get(r.nextReceiver-1);
- if (curReceiver instanceof BroadcastFilter) {
- BroadcastFilter bf = (BroadcastFilter) curReceiver;
- EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
- System.identityHashCode(r),
- r.intent.getAction(),
- r.nextReceiver - 1,
- System.identityHashCode(bf));
- } else {
- EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
- System.identityHashCode(r),
- r.intent.getAction(),
- r.nextReceiver - 1,
- ((ResolveInfo)curReceiver).toString());
- }
- } else {
- Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
- + r);
- EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
- System.identityHashCode(r),
- r.intent.getAction(),
- r.nextReceiver,
- "NONE");
- }
- }
-
- final boolean dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
- int opti, boolean dumpAll, String dumpPackage, boolean needSep) {
- if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
- || mPendingBroadcast != null) {
- boolean printed = false;
- for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
- BroadcastRecord br = mParallelBroadcasts.get(i);
- if (dumpPackage != null && !dumpPackage.equals(br.callerPackage)) {
- continue;
- }
- if (!printed) {
- if (needSep) {
- pw.println();
- needSep = false;
- }
- printed = true;
- pw.println(" Active broadcasts [" + mQueueName + "]:");
- }
- pw.println(" Broadcast #" + i + ":");
- br.dump(pw, " ");
- }
- printed = false;
- needSep = true;
- for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
- BroadcastRecord br = mOrderedBroadcasts.get(i);
- if (dumpPackage != null && !dumpPackage.equals(br.callerPackage)) {
- continue;
- }
- if (!printed) {
- if (needSep) {
- pw.println();
- }
- needSep = true;
- pw.println(" Active ordered broadcasts [" + mQueueName + "]:");
- }
- pw.println(" Ordered Broadcast #" + i + ":");
- mOrderedBroadcasts.get(i).dump(pw, " ");
- }
- if (dumpPackage == null || (mPendingBroadcast != null
- && dumpPackage.equals(mPendingBroadcast.callerPackage))) {
- if (needSep) {
- pw.println();
- }
- pw.println(" Pending broadcast [" + mQueueName + "]:");
- if (mPendingBroadcast != null) {
- mPendingBroadcast.dump(pw, " ");
- } else {
- pw.println(" (null)");
- }
- needSep = true;
- }
- }
-
- boolean printed = false;
- for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
- BroadcastRecord r = mBroadcastHistory[i];
- if (r == null) {
- break;
- }
- if (dumpPackage != null && !dumpPackage.equals(r.callerPackage)) {
- continue;
- }
- if (!printed) {
- if (needSep) {
- pw.println();
- }
- needSep = true;
- pw.println(" Historical broadcasts [" + mQueueName + "]:");
- printed = true;
- }
- if (dumpAll) {
- pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
- r.dump(pw, " ");
- } else {
- if (i >= 50) {
- pw.println(" ...");
- break;
- }
- pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
- }
- }
-
- return needSep;
- }
- }
-
- final BroadcastQueue mFgBroadcastQueue = new BroadcastQueue("foreground", BROADCAST_FG_TIMEOUT);
- final BroadcastQueue mBgBroadcastQueue = new BroadcastQueue("background", BROADCAST_BG_TIMEOUT);
+ BroadcastQueue mFgBroadcastQueue;
+ BroadcastQueue mBgBroadcastQueue;
// Convenient for easy iteration over the queues. Foreground is first
// so that dispatch of foreground broadcasts gets precedence.
- final BroadcastQueue[] mBroadcastQueues = { mFgBroadcastQueue, mBgBroadcastQueue };
+ final BroadcastQueue[] mBroadcastQueues = new BroadcastQueue[2];
BroadcastQueue broadcastQueueForIntent(Intent intent) {
final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
@@ -1625,8 +824,6 @@
static final int UPDATE_CONFIGURATION_MSG = 4;
static final int GC_BACKGROUND_PROCESSES_MSG = 5;
static final int WAIT_FOR_DEBUGGER_MSG = 6;
- static final int BROADCAST_INTENT_MSG = 7;
- static final int BROADCAST_TIMEOUT_MSG = 8;
static final int SERVICE_TIMEOUT_MSG = 12;
static final int UPDATE_TIME_ZONE = 13;
static final int SHOW_UID_ERROR_MSG = 14;
@@ -1646,6 +843,10 @@
static final int DISPATCH_PROCESS_DIED = 32;
static final int REPORT_MEM_USAGE = 33;
+ static final int FIRST_ACTIVITY_STACK_MSG = 100;
+ static final int FIRST_BROADCAST_QUEUE_MSG = 200;
+ static final int FIRST_COMPAT_MODE_MSG = 300;
+
AlertDialog mUidAlert;
CompatModeDialog mCompatModeDialog;
long mLastMemUsageReportTime = 0;
@@ -1765,18 +966,6 @@
}
}
} break;
- case BROADCAST_INTENT_MSG: {
- if (DEBUG_BROADCAST) Slog.v(
- TAG, "Received BROADCAST_INTENT_MSG");
- BroadcastQueue queue = (BroadcastQueue) msg.obj;
- queue.processNextBroadcast(true);
- } break;
- case BROADCAST_TIMEOUT_MSG: {
- final BroadcastQueue queue = (BroadcastQueue) msg.obj;
- synchronized (ActivityManagerService.this) {
- queue.broadcastTimeoutLocked(true);
- }
- } break;
case SERVICE_TIMEOUT_MSG: {
if (mDidDexOpt) {
mDidDexOpt = false;
@@ -2290,6 +1479,11 @@
private ActivityManagerService() {
Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
+ mFgBroadcastQueue = new BroadcastQueue(this, "foreground", BROADCAST_FG_TIMEOUT);
+ mBgBroadcastQueue = new BroadcastQueue(this, "background", BROADCAST_BG_TIMEOUT);
+ mBroadcastQueues[0] = mFgBroadcastQueue;
+ mBroadcastQueues[1] = mBgBroadcastQueue;
+
File dataDir = Environment.getDataDirectory();
File systemDir = new File(dataDir, "system");
systemDir.mkdirs();
@@ -3835,21 +3029,6 @@
}
}
- private final class AppNotResponding implements Runnable {
- private final ProcessRecord mApp;
- private final String mAnnotation;
-
- public AppNotResponding(ProcessRecord app, String annotation) {
- mApp = app;
- mAnnotation = annotation;
- }
-
- @Override
- public void run() {
- appNotResponding(mApp, null, null, mAnnotation);
- }
- }
-
final void appNotResponding(ProcessRecord app, ActivityRecord activity,
ActivityRecord parent, final String annotation) {
ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
@@ -7816,7 +6995,7 @@
/* TODO: Send this to all users */
broadcastIntentLocked(null, null, intent, null, finisher,
0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID,
- Process.SYSTEM_UID);
+ 0 /* UserId zero */);
if (finisher != null) {
mWaitingUpdate = true;
}
@@ -13477,138 +12656,7 @@
Binder.restoreCallingIdentity(origId);
}
}
-
- private final void processCurBroadcastLocked(BroadcastRecord r,
- ProcessRecord app) throws RemoteException {
- if (DEBUG_BROADCAST) Slog.v(TAG,
- "Process cur broadcast " + r + " for app " + app);
- if (app.thread == null) {
- throw new RemoteException();
- }
- r.receiver = app.thread.asBinder();
- r.curApp = app;
- app.curReceiver = r;
- updateLruProcessLocked(app, true, true);
-
- // Tell the application to launch this receiver.
- r.intent.setComponent(r.curComponent);
-
- boolean started = false;
- try {
- if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
- "Delivering to component " + r.curComponent
- + ": " + r);
- ensurePackageDexOpt(r.intent.getComponent().getPackageName());
- app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
- compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
- r.resultCode, r.resultData, r.resultExtras, r.ordered);
- if (DEBUG_BROADCAST) Slog.v(TAG,
- "Process cur broadcast " + r + " DELIVERED for app " + app);
- started = true;
- } finally {
- if (!started) {
- if (DEBUG_BROADCAST) Slog.v(TAG,
- "Process cur broadcast " + r + ": NOT STARTED!");
- r.receiver = null;
- r.curApp = null;
- app.curReceiver = null;
- }
- }
-
- }
-
- static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
- Intent intent, int resultCode, String data, Bundle extras,
- boolean ordered, boolean sticky) throws RemoteException {
- // Send the intent to the receiver asynchronously using one-way binder calls.
- if (app != null && app.thread != null) {
- // If we have an app thread, do the call through that so it is
- // correctly ordered with other one-way calls.
- app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
- data, extras, ordered, sticky);
- } else {
- receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
- }
- }
- private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
- BroadcastFilter filter, boolean ordered) {
- boolean skip = false;
- if (filter.requiredPermission != null) {
- int perm = checkComponentPermission(filter.requiredPermission,
- r.callingPid, r.callingUid, -1, true);
- if (perm != PackageManager.PERMISSION_GRANTED) {
- Slog.w(TAG, "Permission Denial: broadcasting "
- + r.intent.toString()
- + " from " + r.callerPackage + " (pid="
- + r.callingPid + ", uid=" + r.callingUid + ")"
- + " requires " + filter.requiredPermission
- + " due to registered receiver " + filter);
- skip = true;
- }
- }
- if (r.requiredPermission != null) {
- int perm = checkComponentPermission(r.requiredPermission,
- filter.receiverList.pid, filter.receiverList.uid, -1, true);
- if (perm != PackageManager.PERMISSION_GRANTED) {
- Slog.w(TAG, "Permission Denial: receiving "
- + r.intent.toString()
- + " to " + filter.receiverList.app
- + " (pid=" + filter.receiverList.pid
- + ", uid=" + filter.receiverList.uid + ")"
- + " requires " + r.requiredPermission
- + " due to sender " + r.callerPackage
- + " (uid " + r.callingUid + ")");
- skip = true;
- }
- }
-
- if (!skip) {
- // If this is not being sent as an ordered broadcast, then we
- // don't want to touch the fields that keep track of the current
- // state of ordered broadcasts.
- if (ordered) {
- r.receiver = filter.receiverList.receiver.asBinder();
- r.curFilter = filter;
- filter.receiverList.curBroadcast = r;
- r.state = BroadcastRecord.CALL_IN_RECEIVE;
- if (filter.receiverList.app != null) {
- // Bump hosting application to no longer be in background
- // scheduling class. Note that we can't do that if there
- // isn't an app... but we can only be in that case for
- // things that directly call the IActivityManager API, which
- // are already core system stuff so don't matter for this.
- r.curApp = filter.receiverList.app;
- filter.receiverList.app.curReceiver = r;
- updateOomAdjLocked();
- }
- }
- try {
- if (DEBUG_BROADCAST_LIGHT) {
- int seq = r.intent.getIntExtra("seq", -1);
- Slog.i(TAG, "Delivering to " + filter
- + " (seq=" + seq + "): " + r);
- }
- performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
- new Intent(r.intent), r.resultCode,
- r.resultData, r.resultExtras, r.ordered, r.initialSticky);
- if (ordered) {
- r.state = BroadcastRecord.CALL_DONE_RECEIVE;
- }
- } catch (RemoteException e) {
- Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
- if (ordered) {
- r.receiver = null;
- r.curFilter = null;
- filter.receiverList.curBroadcast = null;
- if (filter.receiverList.app != null) {
- filter.receiverList.app.curReceiver = null;
- }
- }
- }
- }
- }
-
// =========================================================
// INSTRUMENTATION
// =========================================================
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index f59f0c1..e8c8275 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -283,13 +283,13 @@
private int mCurrentUser;
- static final int SLEEP_TIMEOUT_MSG = 8;
- static final int PAUSE_TIMEOUT_MSG = 9;
- static final int IDLE_TIMEOUT_MSG = 10;
- static final int IDLE_NOW_MSG = 11;
- static final int LAUNCH_TIMEOUT_MSG = 16;
- static final int DESTROY_TIMEOUT_MSG = 17;
- static final int RESUME_TOP_ACTIVITY_MSG = 19;
+ static final int SLEEP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG;
+ static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
+ static final int IDLE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
+ static final int IDLE_NOW_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
+ static final int LAUNCH_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4;
+ static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5;
+ static final int RESUME_TOP_ACTIVITY_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6;
final Handler mHandler = new Handler() {
//public Handler() {
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java
new file mode 100644
index 0000000..39b63db
--- /dev/null
+++ b/services/java/com/android/server/am/BroadcastQueue.java
@@ -0,0 +1,1017 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+import android.app.AppGlobals;
+import android.content.ComponentName;
+import android.content.IIntentReceiver;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.UserId;
+import android.util.EventLog;
+import android.util.Slog;
+
+/**
+ * BROADCASTS
+ *
+ * We keep two broadcast queues and associated bookkeeping, one for those at
+ * foreground priority, and one for normal (background-priority) broadcasts.
+ */
+public class BroadcastQueue {
+ static final String TAG = "BroadcastQueue";
+ static final String TAG_MU = ActivityManagerService.TAG_MU;
+ static final boolean DEBUG_BROADCAST = ActivityManagerService.DEBUG_BROADCAST;
+ static final boolean DEBUG_BROADCAST_LIGHT = ActivityManagerService.DEBUG_BROADCAST_LIGHT;
+ static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU;
+
+ static final int MAX_BROADCAST_HISTORY = 25;
+
+ final ActivityManagerService mService;
+
+ /**
+ * Recognizable moniker for this queue
+ */
+ final String mQueueName;
+
+ /**
+ * Timeout period for this queue's broadcasts
+ */
+ final long mTimeoutPeriod;
+
+ /**
+ * Lists of all active broadcasts that are to be executed immediately
+ * (without waiting for another broadcast to finish). Currently this only
+ * contains broadcasts to registered receivers, to avoid spinning up
+ * a bunch of processes to execute IntentReceiver components. Background-
+ * and foreground-priority broadcasts are queued separately.
+ */
+ final ArrayList<BroadcastRecord> mParallelBroadcasts
+ = new ArrayList<BroadcastRecord>();
+ /**
+ * List of all active broadcasts that are to be executed one at a time.
+ * The object at the top of the list is the currently activity broadcasts;
+ * those after it are waiting for the top to finish. As with parallel
+ * broadcasts, separate background- and foreground-priority queues are
+ * maintained.
+ */
+ final ArrayList<BroadcastRecord> mOrderedBroadcasts
+ = new ArrayList<BroadcastRecord>();
+
+ /**
+ * Historical data of past broadcasts, for debugging.
+ */
+ final BroadcastRecord[] mBroadcastHistory
+ = new BroadcastRecord[MAX_BROADCAST_HISTORY];
+
+ /**
+ * Set when we current have a BROADCAST_INTENT_MSG in flight.
+ */
+ boolean mBroadcastsScheduled = false;
+
+ /**
+ * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
+ */
+ boolean mPendingBroadcastTimeoutMessage;
+
+ /**
+ * Intent broadcasts that we have tried to start, but are
+ * waiting for the application's process to be created. We only
+ * need one per scheduling class (instead of a list) because we always
+ * process broadcasts one at a time, so no others can be started while
+ * waiting for this one.
+ */
+ BroadcastRecord mPendingBroadcast = null;
+
+ /**
+ * The receiver index that is pending, to restart the broadcast if needed.
+ */
+ int mPendingBroadcastRecvIndex;
+
+ static final int BROADCAST_INTENT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG;
+ static final int BROADCAST_TIMEOUT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 1;
+
+ final Handler mHandler = new Handler() {
+ //public Handler() {
+ // if (localLOGV) Slog.v(TAG, "Handler started!");
+ //}
+
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case BROADCAST_INTENT_MSG: {
+ if (DEBUG_BROADCAST) Slog.v(
+ TAG, "Received BROADCAST_INTENT_MSG");
+ processNextBroadcast(true);
+ } break;
+ case BROADCAST_TIMEOUT_MSG: {
+ synchronized (mService) {
+ broadcastTimeoutLocked(true);
+ }
+ } break;
+ }
+ }
+ };
+
+ private final class AppNotResponding implements Runnable {
+ private final ProcessRecord mApp;
+ private final String mAnnotation;
+
+ public AppNotResponding(ProcessRecord app, String annotation) {
+ mApp = app;
+ mAnnotation = annotation;
+ }
+
+ @Override
+ public void run() {
+ mService.appNotResponding(mApp, null, null, mAnnotation);
+ }
+ }
+
+ BroadcastQueue(ActivityManagerService service, String name, long timeoutPeriod) {
+ mService = service;
+ mQueueName = name;
+ mTimeoutPeriod = timeoutPeriod;
+ }
+
+ public boolean isPendingBroadcastProcessLocked(int pid) {
+ return mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid;
+ }
+
+ public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
+ mParallelBroadcasts.add(r);
+ }
+
+ public void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
+ mOrderedBroadcasts.add(r);
+ }
+
+ public final boolean replaceParallelBroadcastLocked(BroadcastRecord r) {
+ for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
+ if (r.intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "***** DROPPING PARALLEL ["
+ + mQueueName + "]: " + r.intent);
+ mParallelBroadcasts.set(i, r);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public final boolean replaceOrderedBroadcastLocked(BroadcastRecord r) {
+ for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
+ if (r.intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "***** DROPPING ORDERED ["
+ + mQueueName + "]: " + r.intent);
+ mOrderedBroadcasts.set(i, r);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private final void processCurBroadcastLocked(BroadcastRecord r,
+ ProcessRecord app) throws RemoteException {
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Process cur broadcast " + r + " for app " + app);
+ if (app.thread == null) {
+ throw new RemoteException();
+ }
+ r.receiver = app.thread.asBinder();
+ r.curApp = app;
+ app.curReceiver = r;
+ mService.updateLruProcessLocked(app, true, true);
+
+ // Tell the application to launch this receiver.
+ r.intent.setComponent(r.curComponent);
+
+ boolean started = false;
+ try {
+ if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
+ "Delivering to component " + r.curComponent
+ + ": " + r);
+ mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
+ app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
+ mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
+ r.resultCode, r.resultData, r.resultExtras, r.ordered);
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Process cur broadcast " + r + " DELIVERED for app " + app);
+ started = true;
+ } finally {
+ if (!started) {
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Process cur broadcast " + r + ": NOT STARTED!");
+ r.receiver = null;
+ r.curApp = null;
+ app.curReceiver = null;
+ }
+ }
+ }
+
+ public boolean sendPendingBroadcastsLocked(ProcessRecord app) {
+ boolean didSomething = false;
+ final BroadcastRecord br = mPendingBroadcast;
+ if (br != null && br.curApp.pid == app.pid) {
+ try {
+ mPendingBroadcast = null;
+ processCurBroadcastLocked(br, app);
+ didSomething = true;
+ } catch (Exception e) {
+ Slog.w(TAG, "Exception in new application when starting receiver "
+ + br.curComponent.flattenToShortString(), e);
+ logBroadcastReceiverDiscardLocked(br);
+ finishReceiverLocked(br, br.resultCode, br.resultData,
+ br.resultExtras, br.resultAbort, true);
+ scheduleBroadcastsLocked();
+ // We need to reset the state if we fails to start the receiver.
+ br.state = BroadcastRecord.IDLE;
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+ return didSomething;
+ }
+
+ public void skipPendingBroadcastLocked(int pid) {
+ final BroadcastRecord br = mPendingBroadcast;
+ if (br != null && br.curApp.pid == pid) {
+ br.state = BroadcastRecord.IDLE;
+ br.nextReceiver = mPendingBroadcastRecvIndex;
+ mPendingBroadcast = null;
+ scheduleBroadcastsLocked();
+ }
+ }
+
+ public void skipCurrentReceiverLocked(ProcessRecord app) {
+ boolean reschedule = false;
+ BroadcastRecord r = app.curReceiver;
+ if (r != null) {
+ // The current broadcast is waiting for this app's receiver
+ // to be finished. Looks like that's not going to happen, so
+ // let the broadcast continue.
+ logBroadcastReceiverDiscardLocked(r);
+ finishReceiverLocked(r, r.resultCode, r.resultData,
+ r.resultExtras, r.resultAbort, true);
+ reschedule = true;
+ }
+
+ r = mPendingBroadcast;
+ if (r != null && r.curApp == app) {
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "[" + mQueueName + "] skip & discard pending app " + r);
+ logBroadcastReceiverDiscardLocked(r);
+ finishReceiverLocked(r, r.resultCode, r.resultData,
+ r.resultExtras, r.resultAbort, true);
+ reschedule = true;
+ }
+ if (reschedule) {
+ scheduleBroadcastsLocked();
+ }
+ }
+
+ public void scheduleBroadcastsLocked() {
+ if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts ["
+ + mQueueName + "]: current="
+ + mBroadcastsScheduled);
+
+ if (mBroadcastsScheduled) {
+ return;
+ }
+ mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
+ mBroadcastsScheduled = true;
+ }
+
+ public BroadcastRecord getMatchingOrderedReceiver(IBinder receiver) {
+ if (mOrderedBroadcasts.size() > 0) {
+ final BroadcastRecord r = mOrderedBroadcasts.get(0);
+ if (r != null && r.receiver == receiver) {
+ return r;
+ }
+ }
+ return null;
+ }
+
+ public boolean finishReceiverLocked(BroadcastRecord r, int resultCode,
+ String resultData, Bundle resultExtras, boolean resultAbort,
+ boolean explicit) {
+ int state = r.state;
+ r.state = BroadcastRecord.IDLE;
+ if (state == BroadcastRecord.IDLE) {
+ if (explicit) {
+ Slog.w(TAG, "finishReceiver [" + mQueueName + "] called but state is IDLE");
+ }
+ }
+ r.receiver = null;
+ r.intent.setComponent(null);
+ if (r.curApp != null) {
+ r.curApp.curReceiver = null;
+ }
+ if (r.curFilter != null) {
+ r.curFilter.receiverList.curBroadcast = null;
+ }
+ r.curFilter = null;
+ r.curApp = null;
+ r.curComponent = null;
+ r.curReceiver = null;
+ mPendingBroadcast = null;
+
+ r.resultCode = resultCode;
+ r.resultData = resultData;
+ r.resultExtras = resultExtras;
+ r.resultAbort = resultAbort;
+
+ // We will process the next receiver right now if this is finishing
+ // an app receiver (which is always asynchronous) or after we have
+ // come back from calling a receiver.
+ return state == BroadcastRecord.APP_RECEIVE
+ || state == BroadcastRecord.CALL_DONE_RECEIVE;
+ }
+
+ private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
+ Intent intent, int resultCode, String data, Bundle extras,
+ boolean ordered, boolean sticky) throws RemoteException {
+ // Send the intent to the receiver asynchronously using one-way binder calls.
+ if (app != null && app.thread != null) {
+ // If we have an app thread, do the call through that so it is
+ // correctly ordered with other one-way calls.
+ app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
+ data, extras, ordered, sticky);
+ } else {
+ receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
+ }
+ }
+
+ private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
+ BroadcastFilter filter, boolean ordered) {
+ boolean skip = false;
+ if (filter.requiredPermission != null) {
+ int perm = mService.checkComponentPermission(filter.requiredPermission,
+ r.callingPid, r.callingUid, -1, true);
+ if (perm != PackageManager.PERMISSION_GRANTED) {
+ Slog.w(TAG, "Permission Denial: broadcasting "
+ + r.intent.toString()
+ + " from " + r.callerPackage + " (pid="
+ + r.callingPid + ", uid=" + r.callingUid + ")"
+ + " requires " + filter.requiredPermission
+ + " due to registered receiver " + filter);
+ skip = true;
+ }
+ }
+ if (r.requiredPermission != null) {
+ int perm = mService.checkComponentPermission(r.requiredPermission,
+ filter.receiverList.pid, filter.receiverList.uid, -1, true);
+ if (perm != PackageManager.PERMISSION_GRANTED) {
+ Slog.w(TAG, "Permission Denial: receiving "
+ + r.intent.toString()
+ + " to " + filter.receiverList.app
+ + " (pid=" + filter.receiverList.pid
+ + ", uid=" + filter.receiverList.uid + ")"
+ + " requires " + r.requiredPermission
+ + " due to sender " + r.callerPackage
+ + " (uid " + r.callingUid + ")");
+ skip = true;
+ }
+ }
+
+ if (!skip) {
+ // If this is not being sent as an ordered broadcast, then we
+ // don't want to touch the fields that keep track of the current
+ // state of ordered broadcasts.
+ if (ordered) {
+ r.receiver = filter.receiverList.receiver.asBinder();
+ r.curFilter = filter;
+ filter.receiverList.curBroadcast = r;
+ r.state = BroadcastRecord.CALL_IN_RECEIVE;
+ if (filter.receiverList.app != null) {
+ // Bump hosting application to no longer be in background
+ // scheduling class. Note that we can't do that if there
+ // isn't an app... but we can only be in that case for
+ // things that directly call the IActivityManager API, which
+ // are already core system stuff so don't matter for this.
+ r.curApp = filter.receiverList.app;
+ filter.receiverList.app.curReceiver = r;
+ mService.updateOomAdjLocked();
+ }
+ }
+ try {
+ if (DEBUG_BROADCAST_LIGHT) {
+ int seq = r.intent.getIntExtra("seq", -1);
+ Slog.i(TAG, "Delivering to " + filter
+ + " (seq=" + seq + "): " + r);
+ }
+ performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
+ new Intent(r.intent), r.resultCode,
+ r.resultData, r.resultExtras, r.ordered, r.initialSticky);
+ if (ordered) {
+ r.state = BroadcastRecord.CALL_DONE_RECEIVE;
+ }
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
+ if (ordered) {
+ r.receiver = null;
+ r.curFilter = null;
+ filter.receiverList.curBroadcast = null;
+ if (filter.receiverList.app != null) {
+ filter.receiverList.app.curReceiver = null;
+ }
+ }
+ }
+ }
+ }
+
+ final void processNextBroadcast(boolean fromMsg) {
+ synchronized(mService) {
+ BroadcastRecord r;
+
+ if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast ["
+ + mQueueName + "]: "
+ + mParallelBroadcasts.size() + " broadcasts, "
+ + mOrderedBroadcasts.size() + " ordered broadcasts");
+
+ mService.updateCpuStats();
+
+ if (fromMsg) {
+ mBroadcastsScheduled = false;
+ }
+
+ // First, deliver any non-serialized broadcasts right away.
+ while (mParallelBroadcasts.size() > 0) {
+ r = mParallelBroadcasts.remove(0);
+ r.dispatchTime = SystemClock.uptimeMillis();
+ r.dispatchClockTime = System.currentTimeMillis();
+ final int N = r.receivers.size();
+ if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast ["
+ + mQueueName + "] " + r);
+ for (int i=0; i<N; i++) {
+ Object target = r.receivers.get(i);
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Delivering non-ordered on [" + mQueueName + "] to registered "
+ + target + ": " + r);
+ deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
+ }
+ addBroadcastToHistoryLocked(r);
+ if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast ["
+ + mQueueName + "] " + r);
+ }
+
+ // Now take care of the next serialized one...
+
+ // If we are waiting for a process to come up to handle the next
+ // broadcast, then do nothing at this point. Just in case, we
+ // check that the process we're waiting for still exists.
+ if (mPendingBroadcast != null) {
+ if (DEBUG_BROADCAST_LIGHT) {
+ Slog.v(TAG, "processNextBroadcast ["
+ + mQueueName + "]: waiting for "
+ + mPendingBroadcast.curApp);
+ }
+
+ boolean isDead;
+ synchronized (mService.mPidsSelfLocked) {
+ isDead = (mService.mPidsSelfLocked.get(
+ mPendingBroadcast.curApp.pid) == null);
+ }
+ if (!isDead) {
+ // It's still alive, so keep waiting
+ return;
+ } else {
+ Slog.w(TAG, "pending app ["
+ + mQueueName + "]" + mPendingBroadcast.curApp
+ + " died before responding to broadcast");
+ mPendingBroadcast.state = BroadcastRecord.IDLE;
+ mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
+ mPendingBroadcast = null;
+ }
+ }
+
+ boolean looped = false;
+
+ do {
+ if (mOrderedBroadcasts.size() == 0) {
+ // No more broadcasts pending, so all done!
+ mService.scheduleAppGcsLocked();
+ if (looped) {
+ // If we had finished the last ordered broadcast, then
+ // make sure all processes have correct oom and sched
+ // adjustments.
+ mService.updateOomAdjLocked();
+ }
+ return;
+ }
+ r = mOrderedBroadcasts.get(0);
+ boolean forceReceive = false;
+
+ // Ensure that even if something goes awry with the timeout
+ // detection, we catch "hung" broadcasts here, discard them,
+ // and continue to make progress.
+ //
+ // This is only done if the system is ready so that PRE_BOOT_COMPLETED
+ // receivers don't get executed with timeouts. They're intended for
+ // one time heavy lifting after system upgrades and can take
+ // significant amounts of time.
+ int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
+ if (mService.mProcessesReady && r.dispatchTime > 0) {
+ long now = SystemClock.uptimeMillis();
+ if ((numReceivers > 0) &&
+ (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
+ Slog.w(TAG, "Hung broadcast ["
+ + mQueueName + "] discarded after timeout failure:"
+ + " now=" + now
+ + " dispatchTime=" + r.dispatchTime
+ + " startTime=" + r.receiverTime
+ + " intent=" + r.intent
+ + " numReceivers=" + numReceivers
+ + " nextReceiver=" + r.nextReceiver
+ + " state=" + r.state);
+ broadcastTimeoutLocked(false); // forcibly finish this broadcast
+ forceReceive = true;
+ r.state = BroadcastRecord.IDLE;
+ }
+ }
+
+ if (r.state != BroadcastRecord.IDLE) {
+ if (DEBUG_BROADCAST) Slog.d(TAG,
+ "processNextBroadcast("
+ + mQueueName + ") called when not idle (state="
+ + r.state + ")");
+ return;
+ }
+
+ if (r.receivers == null || r.nextReceiver >= numReceivers
+ || r.resultAbort || forceReceive) {
+ // No more receivers for this broadcast! Send the final
+ // result if requested...
+ if (r.resultTo != null) {
+ try {
+ if (DEBUG_BROADCAST) {
+ int seq = r.intent.getIntExtra("seq", -1);
+ Slog.i(TAG, "Finishing broadcast ["
+ + mQueueName + "] " + r.intent.getAction()
+ + " seq=" + seq + " app=" + r.callerApp);
+ }
+ performReceiveLocked(r.callerApp, r.resultTo,
+ new Intent(r.intent), r.resultCode,
+ r.resultData, r.resultExtras, false, false);
+ // Set this to null so that the reference
+ // (local and remote) isnt kept in the mBroadcastHistory.
+ r.resultTo = null;
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failure ["
+ + mQueueName + "] sending broadcast result of "
+ + r.intent, e);
+ }
+ }
+
+ if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
+ cancelBroadcastTimeoutLocked();
+
+ if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
+ + r);
+
+ // ... and on to the next...
+ addBroadcastToHistoryLocked(r);
+ mOrderedBroadcasts.remove(0);
+ r = null;
+ looped = true;
+ continue;
+ }
+ } while (r == null);
+
+ // Get the next receiver...
+ int recIdx = r.nextReceiver++;
+
+ // Keep track of when this receiver started, and make sure there
+ // is a timeout message pending to kill it if need be.
+ r.receiverTime = SystemClock.uptimeMillis();
+ if (recIdx == 0) {
+ r.dispatchTime = r.receiverTime;
+ r.dispatchClockTime = System.currentTimeMillis();
+ if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast ["
+ + mQueueName + "] " + r);
+ }
+ if (! mPendingBroadcastTimeoutMessage) {
+ long timeoutTime = r.receiverTime + mTimeoutPeriod;
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Submitting BROADCAST_TIMEOUT_MSG ["
+ + mQueueName + "] for " + r + " at " + timeoutTime);
+ setBroadcastTimeoutLocked(timeoutTime);
+ }
+
+ Object nextReceiver = r.receivers.get(recIdx);
+ if (nextReceiver instanceof BroadcastFilter) {
+ // Simple case: this is a registered receiver who gets
+ // a direct call.
+ BroadcastFilter filter = (BroadcastFilter)nextReceiver;
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Delivering ordered ["
+ + mQueueName + "] to registered "
+ + filter + ": " + r);
+ deliverToRegisteredReceiverLocked(r, filter, r.ordered);
+ if (r.receiver == null || !r.ordered) {
+ // The receiver has already finished, so schedule to
+ // process the next one.
+ if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing ["
+ + mQueueName + "]: ordered="
+ + r.ordered + " receiver=" + r.receiver);
+ r.state = BroadcastRecord.IDLE;
+ scheduleBroadcastsLocked();
+ }
+ return;
+ }
+
+ // Hard case: need to instantiate the receiver, possibly
+ // starting its application process to host it.
+
+ ResolveInfo info =
+ (ResolveInfo)nextReceiver;
+
+ boolean skip = false;
+ int perm = mService.checkComponentPermission(info.activityInfo.permission,
+ r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
+ info.activityInfo.exported);
+ if (perm != PackageManager.PERMISSION_GRANTED) {
+ if (!info.activityInfo.exported) {
+ Slog.w(TAG, "Permission Denial: broadcasting "
+ + r.intent.toString()
+ + " from " + r.callerPackage + " (pid=" + r.callingPid
+ + ", uid=" + r.callingUid + ")"
+ + " is not exported from uid " + info.activityInfo.applicationInfo.uid
+ + " due to receiver " + info.activityInfo.packageName
+ + "/" + info.activityInfo.name);
+ } else {
+ Slog.w(TAG, "Permission Denial: broadcasting "
+ + r.intent.toString()
+ + " from " + r.callerPackage + " (pid=" + r.callingPid
+ + ", uid=" + r.callingUid + ")"
+ + " requires " + info.activityInfo.permission
+ + " due to receiver " + info.activityInfo.packageName
+ + "/" + info.activityInfo.name);
+ }
+ skip = true;
+ }
+ if (info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
+ r.requiredPermission != null) {
+ try {
+ perm = AppGlobals.getPackageManager().
+ checkPermission(r.requiredPermission,
+ info.activityInfo.applicationInfo.packageName);
+ } catch (RemoteException e) {
+ perm = PackageManager.PERMISSION_DENIED;
+ }
+ if (perm != PackageManager.PERMISSION_GRANTED) {
+ Slog.w(TAG, "Permission Denial: receiving "
+ + r.intent + " to "
+ + info.activityInfo.applicationInfo.packageName
+ + " requires " + r.requiredPermission
+ + " due to sender " + r.callerPackage
+ + " (uid " + r.callingUid + ")");
+ skip = true;
+ }
+ }
+ if (r.curApp != null && r.curApp.crashing) {
+ // If the target process is crashing, just skip it.
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Skipping deliver ordered ["
+ + mQueueName + "] " + r + " to " + r.curApp
+ + ": process crashing");
+ skip = true;
+ }
+
+ if (skip) {
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Skipping delivery of ordered ["
+ + mQueueName + "] " + r + " for whatever reason");
+ r.receiver = null;
+ r.curFilter = null;
+ r.state = BroadcastRecord.IDLE;
+ scheduleBroadcastsLocked();
+ return;
+ }
+
+ r.state = BroadcastRecord.APP_RECEIVE;
+ String targetProcess = info.activityInfo.processName;
+ r.curComponent = new ComponentName(
+ info.activityInfo.applicationInfo.packageName,
+ info.activityInfo.name);
+ if (r.callingUid != Process.SYSTEM_UID) {
+ info.activityInfo = mService.getActivityInfoForUser(info.activityInfo, UserId
+ .getUserId(r.callingUid));
+ }
+ r.curReceiver = info.activityInfo;
+ if (DEBUG_MU && r.callingUid > UserId.PER_USER_RANGE) {
+ Slog.v(TAG_MU, "Updated broadcast record activity info for secondary user, "
+ + info.activityInfo + ", callingUid = " + r.callingUid + ", uid = "
+ + info.activityInfo.applicationInfo.uid);
+ }
+
+ // Broadcast is being executed, its package can't be stopped.
+ try {
+ AppGlobals.getPackageManager().setPackageStoppedState(
+ r.curComponent.getPackageName(), false);
+ } catch (RemoteException e) {
+ } catch (IllegalArgumentException e) {
+ Slog.w(TAG, "Failed trying to unstop package "
+ + r.curComponent.getPackageName() + ": " + e);
+ }
+
+ // Is this receiver's application already running?
+ ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
+ info.activityInfo.applicationInfo.uid);
+ if (app != null && app.thread != null) {
+ try {
+ app.addPackage(info.activityInfo.packageName);
+ processCurBroadcastLocked(r, app);
+ return;
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Exception when sending broadcast to "
+ + r.curComponent, e);
+ }
+
+ // If a dead object exception was thrown -- fall through to
+ // restart the application.
+ }
+
+ // Not running -- get it started, to be executed when the app comes up.
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Need to start app ["
+ + mQueueName + "] " + targetProcess + " for broadcast " + r);
+ if ((r.curApp=mService.startProcessLocked(targetProcess,
+ info.activityInfo.applicationInfo, true,
+ r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
+ "broadcast", r.curComponent,
+ (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false))
+ == null) {
+ // Ah, this recipient is unavailable. Finish it if necessary,
+ // and mark the broadcast record as ready for the next.
+ Slog.w(TAG, "Unable to launch app "
+ + info.activityInfo.applicationInfo.packageName + "/"
+ + info.activityInfo.applicationInfo.uid + " for broadcast "
+ + r.intent + ": process is bad");
+ logBroadcastReceiverDiscardLocked(r);
+ finishReceiverLocked(r, r.resultCode, r.resultData,
+ r.resultExtras, r.resultAbort, true);
+ scheduleBroadcastsLocked();
+ r.state = BroadcastRecord.IDLE;
+ return;
+ }
+
+ mPendingBroadcast = r;
+ mPendingBroadcastRecvIndex = recIdx;
+ }
+ }
+
+ final void setBroadcastTimeoutLocked(long timeoutTime) {
+ if (! mPendingBroadcastTimeoutMessage) {
+ Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG, this);
+ mHandler.sendMessageAtTime(msg, timeoutTime);
+ mPendingBroadcastTimeoutMessage = true;
+ }
+ }
+
+ final void cancelBroadcastTimeoutLocked() {
+ if (mPendingBroadcastTimeoutMessage) {
+ mHandler.removeMessages(BROADCAST_TIMEOUT_MSG, this);
+ mPendingBroadcastTimeoutMessage = false;
+ }
+ }
+
+ final void broadcastTimeoutLocked(boolean fromMsg) {
+ if (fromMsg) {
+ mPendingBroadcastTimeoutMessage = false;
+ }
+
+ if (mOrderedBroadcasts.size() == 0) {
+ return;
+ }
+
+ long now = SystemClock.uptimeMillis();
+ BroadcastRecord r = mOrderedBroadcasts.get(0);
+ if (fromMsg) {
+ if (mService.mDidDexOpt) {
+ // Delay timeouts until dexopt finishes.
+ mService.mDidDexOpt = false;
+ long timeoutTime = SystemClock.uptimeMillis() + mTimeoutPeriod;
+ setBroadcastTimeoutLocked(timeoutTime);
+ return;
+ }
+ if (!mService.mProcessesReady) {
+ // Only process broadcast timeouts if the system is ready. That way
+ // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
+ // to do heavy lifting for system up.
+ return;
+ }
+
+ long timeoutTime = r.receiverTime + mTimeoutPeriod;
+ if (timeoutTime > now) {
+ // We can observe premature timeouts because we do not cancel and reset the
+ // broadcast timeout message after each receiver finishes. Instead, we set up
+ // an initial timeout then kick it down the road a little further as needed
+ // when it expires.
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Premature timeout ["
+ + mQueueName + "] @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
+ + timeoutTime);
+ setBroadcastTimeoutLocked(timeoutTime);
+ return;
+ }
+ }
+
+ Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
+ + ", started " + (now - r.receiverTime) + "ms ago");
+ r.receiverTime = now;
+ r.anrCount++;
+
+ // Current receiver has passed its expiration date.
+ if (r.nextReceiver <= 0) {
+ Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
+ return;
+ }
+
+ ProcessRecord app = null;
+ String anrMessage = null;
+
+ Object curReceiver = r.receivers.get(r.nextReceiver-1);
+ Slog.w(TAG, "Receiver during timeout: " + curReceiver);
+ logBroadcastReceiverDiscardLocked(r);
+ if (curReceiver instanceof BroadcastFilter) {
+ BroadcastFilter bf = (BroadcastFilter)curReceiver;
+ if (bf.receiverList.pid != 0
+ && bf.receiverList.pid != ActivityManagerService.MY_PID) {
+ synchronized (mService.mPidsSelfLocked) {
+ app = mService.mPidsSelfLocked.get(
+ bf.receiverList.pid);
+ }
+ }
+ } else {
+ app = r.curApp;
+ }
+
+ if (app != null) {
+ anrMessage = "Broadcast of " + r.intent.toString();
+ }
+
+ if (mPendingBroadcast == r) {
+ mPendingBroadcast = null;
+ }
+
+ // Move on to the next receiver.
+ finishReceiverLocked(r, r.resultCode, r.resultData,
+ r.resultExtras, r.resultAbort, true);
+ scheduleBroadcastsLocked();
+
+ if (anrMessage != null) {
+ // Post the ANR to the handler since we do not want to process ANRs while
+ // potentially holding our lock.
+ mHandler.post(new AppNotResponding(app, anrMessage));
+ }
+ }
+
+ private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
+ if (r.callingUid < 0) {
+ // This was from a registerReceiver() call; ignore it.
+ return;
+ }
+ System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
+ MAX_BROADCAST_HISTORY-1);
+ r.finishTime = SystemClock.uptimeMillis();
+ mBroadcastHistory[0] = r;
+ }
+
+ final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
+ if (r.nextReceiver > 0) {
+ Object curReceiver = r.receivers.get(r.nextReceiver-1);
+ if (curReceiver instanceof BroadcastFilter) {
+ BroadcastFilter bf = (BroadcastFilter) curReceiver;
+ EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
+ System.identityHashCode(r),
+ r.intent.getAction(),
+ r.nextReceiver - 1,
+ System.identityHashCode(bf));
+ } else {
+ EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
+ System.identityHashCode(r),
+ r.intent.getAction(),
+ r.nextReceiver - 1,
+ ((ResolveInfo)curReceiver).toString());
+ }
+ } else {
+ Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
+ + r);
+ EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
+ System.identityHashCode(r),
+ r.intent.getAction(),
+ r.nextReceiver,
+ "NONE");
+ }
+ }
+
+ final boolean dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
+ int opti, boolean dumpAll, String dumpPackage, boolean needSep) {
+ if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
+ || mPendingBroadcast != null) {
+ boolean printed = false;
+ for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
+ BroadcastRecord br = mParallelBroadcasts.get(i);
+ if (dumpPackage != null && !dumpPackage.equals(br.callerPackage)) {
+ continue;
+ }
+ if (!printed) {
+ if (needSep) {
+ pw.println();
+ needSep = false;
+ }
+ printed = true;
+ pw.println(" Active broadcasts [" + mQueueName + "]:");
+ }
+ pw.println(" Broadcast #" + i + ":");
+ br.dump(pw, " ");
+ }
+ printed = false;
+ needSep = true;
+ for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
+ BroadcastRecord br = mOrderedBroadcasts.get(i);
+ if (dumpPackage != null && !dumpPackage.equals(br.callerPackage)) {
+ continue;
+ }
+ if (!printed) {
+ if (needSep) {
+ pw.println();
+ }
+ needSep = true;
+ pw.println(" Active ordered broadcasts [" + mQueueName + "]:");
+ }
+ pw.println(" Ordered Broadcast #" + i + ":");
+ mOrderedBroadcasts.get(i).dump(pw, " ");
+ }
+ if (dumpPackage == null || (mPendingBroadcast != null
+ && dumpPackage.equals(mPendingBroadcast.callerPackage))) {
+ if (needSep) {
+ pw.println();
+ }
+ pw.println(" Pending broadcast [" + mQueueName + "]:");
+ if (mPendingBroadcast != null) {
+ mPendingBroadcast.dump(pw, " ");
+ } else {
+ pw.println(" (null)");
+ }
+ needSep = true;
+ }
+ }
+
+ boolean printed = false;
+ for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
+ BroadcastRecord r = mBroadcastHistory[i];
+ if (r == null) {
+ break;
+ }
+ if (dumpPackage != null && !dumpPackage.equals(r.callerPackage)) {
+ continue;
+ }
+ if (!printed) {
+ if (needSep) {
+ pw.println();
+ }
+ needSep = true;
+ pw.println(" Historical broadcasts [" + mQueueName + "]:");
+ printed = true;
+ }
+ if (dumpAll) {
+ pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
+ r.dump(pw, " ");
+ } else {
+ if (i >= 50) {
+ pw.println(" ...");
+ break;
+ }
+ pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
+ }
+ }
+
+ return needSep;
+ }
+}
diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/java/com/android/server/am/BroadcastRecord.java
index 6738e4f..dd560fc 100644
--- a/services/java/com/android/server/am/BroadcastRecord.java
+++ b/services/java/com/android/server/am/BroadcastRecord.java
@@ -59,7 +59,7 @@
IBinder receiver; // who is currently running, null if none.
int state;
int anrCount; // has this broadcast record hit any ANRs?
- ActivityManagerService.BroadcastQueue queue; // the outbound queue handling this broadcast
+ BroadcastQueue queue; // the outbound queue handling this broadcast
static final int IDLE = 0;
static final int APP_RECEIVE = 1;
@@ -162,7 +162,7 @@
}
}
- BroadcastRecord(ActivityManagerService.BroadcastQueue _queue,
+ BroadcastRecord(BroadcastQueue _queue,
Intent _intent, ProcessRecord _callerApp, String _callerPackage,
int _callingPid, int _callingUid, String _requiredPermission,
List _receivers, IIntentReceiver _resultTo, int _resultCode,
diff --git a/services/java/com/android/server/am/CompatModePackages.java b/services/java/com/android/server/am/CompatModePackages.java
index f6564862..cd72202 100644
--- a/services/java/com/android/server/am/CompatModePackages.java
+++ b/services/java/com/android/server/am/CompatModePackages.java
@@ -41,7 +41,7 @@
private final HashMap<String, Integer> mPackages = new HashMap<String, Integer>();
- private static final int MSG_WRITE = 1;
+ private static final int MSG_WRITE = ActivityManagerService.FIRST_COMPAT_MODE_MSG;
private final Handler mHandler = new Handler() {
@Override public void handleMessage(Message msg) {
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 55fb038..04a039f 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import java.io.PrintWriter;
+
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
@@ -96,6 +98,46 @@
final Matrix mTmpMatrix = new Matrix();
final float[] mTmpFloats = new float[9];
+ public void printTo(String prefix, PrintWriter pw) {
+ pw.print(prefix); pw.print("mSurface="); pw.print(mSurface);
+ pw.print(" mWidth="); pw.print(mWidth);
+ pw.print(" mHeight="); pw.println(mHeight);
+ pw.print(prefix); pw.print("mBlackFrame="); pw.println(mBlackFrame);
+ pw.print(prefix); pw.print("mSnapshotRotation="); pw.print(mSnapshotRotation);
+ pw.print(" mSnapshotDeltaRotation="); pw.print(mSnapshotDeltaRotation);
+ pw.print(" mCurRotation="); pw.println(mCurRotation);
+ pw.print(prefix); pw.print("mOriginalRotation="); pw.print(mOriginalRotation);
+ pw.print(" mOriginalWidth="); pw.print(mOriginalWidth);
+ pw.print(" mOriginalHeight="); pw.println(mOriginalHeight);
+ pw.print(prefix); pw.print("mStarted="); pw.print(mStarted);
+ pw.print(" mAnimRunning="); pw.print(mAnimRunning);
+ pw.print(" mFinishAnimReady="); pw.print(mFinishAnimReady);
+ pw.print(" mFinishAnimStartTime="); pw.println(mFinishAnimStartTime);
+ pw.print(prefix); pw.print("mStartExitAnimation="); pw.print(mStartExitAnimation);
+ pw.print(" "); mStartExitTransformation.printShortString(pw); pw.println();
+ pw.print(prefix); pw.print("mStartEnterAnimation="); pw.print(mStartEnterAnimation);
+ pw.print(" "); mStartEnterTransformation.printShortString(pw); pw.println();
+ pw.print(prefix); pw.print("mFinishExitAnimation="); pw.print(mFinishExitAnimation);
+ pw.print(" "); mFinishExitTransformation.printShortString(pw); pw.println();
+ pw.print(prefix); pw.print("mFinishEnterAnimation="); pw.print(mFinishEnterAnimation);
+ pw.print(" "); mFinishEnterTransformation.printShortString(pw); pw.println();
+ pw.print(prefix); pw.print("mRotateExitAnimation="); pw.print(mRotateExitAnimation);
+ pw.print(" "); mRotateExitTransformation.printShortString(pw); pw.println();
+ pw.print(prefix); pw.print("mRotateEnterAnimation="); pw.print(mRotateEnterAnimation);
+ pw.print(" "); mRotateEnterTransformation.printShortString(pw); pw.println();
+ pw.print(prefix); pw.print("mLastRotateExitAnimation=");
+ pw.print(mLastRotateExitAnimation);
+ pw.print(" "); mLastRotateExitTransformation.printShortString(pw); pw.println();
+ pw.print(prefix); pw.print("mExitTransformation=");
+ mExitTransformation.printShortString(pw); pw.println();
+ pw.print(prefix); pw.print("mEnterTransformation=");
+ mEnterTransformation.printShortString(pw); pw.println();
+ pw.print(prefix); pw.print("mSnapshotInitialMatrix=");
+ mSnapshotInitialMatrix.printShortString(pw);
+ pw.print(" mSnapshotFinalMatrix="); mSnapshotFinalMatrix.printShortString(pw);
+ pw.println();
+ }
+
public ScreenRotationAnimation(Context context, SurfaceSession session,
boolean inTransaction, int originalWidth, int originalHeight, int originalRotation) {
mContext = context;
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 3b5ec03..bdbaab4 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -7636,6 +7636,8 @@
mInnerFields.mAnimating = true;
} else {
updateRotation = true;
+ mScreenRotationAnimation.kill();
+ mScreenRotationAnimation = null;
}
}
}
@@ -8708,7 +8710,7 @@
mInnerFields.mAnimating = false;
// SECOND LOOP: Execute animations and update visibility of windows.
- updateRotation =
+ updateRotation |=
updateAppsAndRotationAnimationsLocked(currentTime, innerDw, innerDh);
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: seq="
@@ -9012,11 +9014,6 @@
mTurnOnScreen = false;
}
- if (updateRotation && mScreenRotationAnimation != null) {
- mScreenRotationAnimation.kill();
- mScreenRotationAnimation = null;
- }
-
if (updateRotation) {
if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
if (updateRotationUncheckedLocked(false)) {
@@ -9387,7 +9384,7 @@
}
if (CUSTOM_SCREEN_ROTATION) {
- if (mScreenRotationAnimation != null && mScreenRotationAnimation.isAnimating()) {
+ if (mScreenRotationAnimation != null) {
mScreenRotationAnimation.kill();
mScreenRotationAnimation = null;
}
@@ -9918,11 +9915,15 @@
pw.print(" mLastWindowForcedOrientation"); pw.print(mLastWindowForcedOrientation);
pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
- pw.print(" mTraversalScheduled="); pw.print(mTraversalScheduled);
- pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale);
- pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale);
+ if (mScreenRotationAnimation != null) {
+ pw.println(" mScreenRotationAnimation:");
+ mScreenRotationAnimation.printTo(" ", pw);
+ }
+ pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale);
+ pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale);
pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale);
- pw.print(" mNextAppTransition=0x");
+ pw.print(" mTraversalScheduled="); pw.print(mTraversalScheduled);
+ pw.print(" mNextAppTransition=0x");
pw.print(Integer.toHexString(mNextAppTransition));
pw.print(" mAppTransitionReady="); pw.println(mAppTransitionReady);
pw.print(" mAppTransitionRunning="); pw.print(mAppTransitionRunning);
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 5da3d97..24a4876 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1438,7 +1438,8 @@
* phoneNumber doesn't have the country code.
* @param defaultCountryIso
* the ISO 3166-1 two letters country code whose convention will
- * be used if the phoneNumberE164 is null or invalid.
+ * be used if the phoneNumberE164 is null or invalid, or if phoneNumber
+ * contains IDD.
* @return the formatted number if the given number has been formatted,
* otherwise, return the given number.
*
@@ -1457,9 +1458,13 @@
if (phoneNumberE164 != null && phoneNumberE164.length() >= 2
&& phoneNumberE164.charAt(0) == '+') {
try {
- PhoneNumber pn = util.parse(phoneNumberE164, defaultCountryIso);
+ // The number to be parsed is in E164 format, so the default region used doesn't
+ // matter.
+ PhoneNumber pn = util.parse(phoneNumberE164, "ZZ");
String regionCode = util.getRegionCodeForNumber(pn);
- if (!TextUtils.isEmpty(regionCode)) {
+ if (!TextUtils.isEmpty(regionCode) &&
+ // This makes sure phoneNumber doesn't contain an IDD
+ normalizeNumber(phoneNumber).indexOf(phoneNumberE164.substring(1)) <= 0) {
defaultCountryIso = regionCode;
}
} catch (NumberParseException e) {
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
index 5b76272..9d9680d 100644
--- a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
@@ -512,6 +512,9 @@
public void testFormatNumber() {
assertEquals("(650) 291-0000", PhoneNumberUtils.formatNumber("650 2910000", "US"));
assertEquals("223-4567", PhoneNumberUtils.formatNumber("2234567", "US"));
+ assertEquals("011 86 10 8888 0000",
+ PhoneNumberUtils.formatNumber("011861088880000", "US"));
+ assertEquals("010 8888 0000", PhoneNumberUtils.formatNumber("01088880000", "CN"));
// formatNumber doesn't format alpha numbers, but keep them as they are.
assertEquals("800-GOOG-114", PhoneNumberUtils.formatNumber("800-GOOG-114", "US"));
}
@@ -542,6 +545,16 @@
// Using the phoneNumberE164's country code
assertEquals("(650) 291-0000",
PhoneNumberUtils.formatNumber("6502910000", "+16502910000", "CN"));
+ // Using the default country code for a phone number containing the IDD
+ assertEquals("011 86 10 8888 0000",
+ PhoneNumberUtils.formatNumber("011861088880000", "+861088880000", "US"));
+ assertEquals("00 86 10 8888 0000",
+ PhoneNumberUtils.formatNumber("00861088880000", "+861088880000", "GB"));
+ assertEquals("+86 10 8888 0000",
+ PhoneNumberUtils.formatNumber("+861088880000", "+861088880000", "GB"));
+ // Wrong default country, so no formatting is done
+ assertEquals("011861088880000",
+ PhoneNumberUtils.formatNumber("011861088880000", "+861088880000", "GB"));
// The phoneNumberE164 is null
assertEquals("(650) 291-0000", PhoneNumberUtils.formatNumber("6502910000", null, "US"));
// The given number has a country code.
@@ -553,7 +566,11 @@
// An invalid Polish number should be left as it is. Note Poland doesn't use '0' as a
// national prefix; therefore, the leading '0' makes the number invalid.
assertEquals("0506128687", PhoneNumberUtils.formatNumber("0506128687", null, "PL"));
+ // Wrong default country, so no formatting is done
+ assertEquals("011861088880000",
+ PhoneNumberUtils.formatNumber("011861088880000", "", "GB"));
}
+
@SmallTest
public void testIsEmergencyNumber() {
// There are two parallel sets of tests here: one for the
diff --git a/tests/BiDiTests/res/layout/grid_layout_ltr.xml b/tests/BiDiTests/res/layout/grid_layout_ltr.xml
index 46ea658..e320809 100644
--- a/tests/BiDiTests/res/layout/grid_layout_ltr.xml
+++ b/tests/BiDiTests/res/layout/grid_layout_ltr.xml
@@ -57,6 +57,27 @@
<EditText
android:ems="8"/>
+ <TextView
+ android:text="You can configure email in just a few steps:"
+ android:textSize="16dip"
+ android:layout_columnSpan="4"
+ android:layout_gravity="start"/>
+
+ <TextView
+ android:text="Email address:"
+ android:layout_gravity="end"/>
+
+ <EditText
+ android:ems="10"/>
+
+ <TextView
+ android:text="Password:"
+ android:layout_column="0"
+ android:layout_gravity="end"/>
+
+ <EditText
+ android:ems="8"/>
+
<Space
android:layout_row="4"
android:layout_column="0"
diff --git a/tests/BiDiTests/res/layout/grid_layout_rtl.xml b/tests/BiDiTests/res/layout/grid_layout_rtl.xml
index 947e13c..6d3aae6 100644
--- a/tests/BiDiTests/res/layout/grid_layout_rtl.xml
+++ b/tests/BiDiTests/res/layout/grid_layout_rtl.xml
@@ -57,6 +57,27 @@
<EditText
android:ems="8"/>
+ <TextView
+ android:text="You can configure email in just a few steps:"
+ android:textSize="16dip"
+ android:layout_columnSpan="4"
+ android:layout_gravity="end"/>
+
+ <TextView
+ android:text="Email address:"
+ android:layout_gravity="start"/>
+
+ <EditText
+ android:ems="10"/>
+
+ <TextView
+ android:text="Password:"
+ android:layout_column="0"
+ android:layout_gravity="start"/>
+
+ <EditText
+ android:ems="8"/>
+
<Space
android:layout_row="4"
android:layout_column="0"
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeLtr.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeLtr.java
index 859b8fb..2b5e674 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeLtr.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeLtr.java
@@ -23,7 +23,6 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridLayout;
-
import android.widget.*;
import static android.text.InputType.*;
@@ -62,8 +61,8 @@
Spec row7 = spec(6);
Spec col1a = spec(0, 4, CENTER);
- Spec col1b = spec(0, 4, START);
- Spec col1c = spec(0, END);
+ Spec col1b = spec(0, 4, LEFT);
+ Spec col1c = spec(0, RIGHT);
Spec col2 = spec(1, START);
Spec col3 = spec(2, FILL);
Spec col4a = spec(3);
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeRtl.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeRtl.java
index fac8c95..3a03c6c 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeRtl.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeRtl.java
@@ -22,6 +22,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.GridLayout;
import android.widget.*;
import static android.text.InputType.*;
@@ -60,8 +61,8 @@
Spec row7 = spec(6);
Spec col1a = spec(0, 4, CENTER);
- Spec col1b = spec(0, 4, START);
- Spec col1c = spec(0, END);
+ Spec col1b = spec(0, 4, LEFT);
+ Spec col1c = spec(0, RIGHT);
Spec col2 = spec(1, START);
Spec col3 = spec(2, FILL);
Spec col4a = spec(3);
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index c0ba8cf..83c9c3d 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -22,12 +22,12 @@
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
import android.graphics.Bitmap;
-import android.graphics.Canvas;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
+import android.graphics.Canvas;
import android.net.http.SslError;
import android.os.Bundle;
import android.os.Environment;
@@ -36,7 +36,6 @@
import android.util.Log;
import android.view.ViewGroup;
import android.view.Window;
-import android.webkit.CookieManager;
import android.webkit.ConsoleMessage;
import android.webkit.CookieManager;
import android.webkit.GeolocationPermissions;
@@ -904,9 +903,7 @@
settings.setWorkersEnabled(false);
settings.setXSSAuditorEnabled(false);
settings.setPageCacheCapacity(0);
- // this enables cpu upload path (as opposed to gpu upload path)
- // and it's only meant to be a temporary workaround!
- settings.setProperty("enable_cpu_upload_path", "true");
+ settings.setProperty("use_minimal_memory", "false");
}
private WebView mWebView;
diff --git a/tests/RenderScriptTests/ComputePerf/src/com/example/android/rs/computeperf/mandelbrot.rs b/tests/RenderScriptTests/ComputePerf/src/com/example/android/rs/computeperf/mandelbrot.rs
index a7987b3..0ffb0e5 100644
--- a/tests/RenderScriptTests/ComputePerf/src/com/example/android/rs/computeperf/mandelbrot.rs
+++ b/tests/RenderScriptTests/ComputePerf/src/com/example/android/rs/computeperf/mandelbrot.rs
@@ -25,13 +25,14 @@
p.y = -1.f + ((float)y / gDimY) * 2.f;
float2 t = 0;
+ float2 t2 = t * t;
int iteration = 0;
- while((t.x*t.x + t.y*t.y < 4.f) && (iteration < gMaxIteration)) {
- float2 t2 = t * t;
+ while((t2.x + t2.y < 4.f) && (iteration < gMaxIteration)) {
float xtemp = t2.x - t2.y + p.x;
t.y = 2 * t.x * t.y + p.y;
t.x = xtemp;
iteration++;
+ t2 = t * t;
}
if(iteration >= gMaxIteration) {
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
index 3615f60..7368260 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -283,6 +283,9 @@
mRadius = MAX_RADIUS;
mScript.set_radius(mRadius);
+ mScript.invoke_filter();
+ mRS.finish();
+
long t = java.lang.System.currentTimeMillis();
mScript.invoke_filter();
diff --git a/tests/RenderScriptTests/PerfTest/res/raw/singletexfm.glsl b/tests/RenderScriptTests/PerfTest/res/raw/singletexfm.glsl
new file mode 100644
index 0000000..656961c
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/res/raw/singletexfm.glsl
@@ -0,0 +1,8 @@
+varying vec2 varTex0;
+
+void main() {
+ lowp vec3 col0 = texture2D(UNI_Tex0, varTex0).rgb;
+ gl_FragColor.xyz = col0 * UNI_modulate.rgb;
+ gl_FragColor.w = UNI_modulate.a;
+}
+
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/FillTest.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/FillTest.java
index ba70c71..41f664a 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/FillTest.java
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/FillTest.java
@@ -35,18 +35,22 @@
// Custom shaders
private ProgramFragment mProgFragmentMultitex;
private ProgramFragment mProgFragmentSingletex;
+ private ProgramFragment mProgFragmentSingletexModulate;
private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
int mBenchmarkDimX;
int mBenchmarkDimY;
private ScriptC_fill_test mFillScript;
ScriptField_TestScripts_s.Item[] mTests;
+ ScriptField_FillTestFragData_s mFragData;
private final String[] mNames = {
"Fill screen 10x singletexture",
"Fill screen 10x 3tex multitexture",
"Fill screen 10x blended singletexture",
- "Fill screen 10x blended 3tex multitexture"
+ "Fill screen 10x blended 3tex multitexture",
+ "Fill screen 3x modulate blended singletexture",
+ "Fill screen 1x modulate blended singletexture",
};
public FillTest() {
@@ -88,6 +92,8 @@
addTest(index++, 0 /*testId*/, 0 /*blend*/, 10 /*quadCount*/);
addTest(index++, 1 /*testId*/, 1 /*blend*/, 10 /*quadCount*/);
addTest(index++, 0 /*testId*/, 1 /*blend*/, 10 /*quadCount*/);
+ addTest(index++, 2 /*testId*/, 1 /*blend*/, 3 /*quadCount*/);
+ addTest(index++, 2 /*testId*/, 1 /*blend*/, 1 /*quadCount*/);
return true;
}
@@ -112,6 +118,14 @@
pfbCustom.setShader(mRes, R.raw.singletexf);
pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
mProgFragmentSingletex = pfbCustom.create();
+
+ pfbCustom = new ProgramFragment.Builder(mRS);
+ pfbCustom.setShader(mRes, R.raw.singletexfm);
+ pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
+ mFragData = new ScriptField_FillTestFragData_s(mRS, 1);
+ pfbCustom.addConstant(mFragData.getType());
+ mProgFragmentSingletexModulate = pfbCustom.create();
+ mProgFragmentSingletexModulate.bindConstants(mFragData.getAllocation(), 0);
}
private Allocation loadTextureARGB(int id) {
@@ -140,6 +154,7 @@
mFillScript.set_gProgVertex(progVertex);
mFillScript.set_gProgFragmentTexture(mProgFragmentSingletex);
+ mFillScript.set_gProgFragmentTextureModulate(mProgFragmentSingletexModulate);
mFillScript.set_gProgFragmentMultitex(mProgFragmentMultitex);
mFillScript.set_gProgStoreBlendNone(ProgramStore.BLEND_NONE_DEPTH_NONE(mRS));
mFillScript.set_gProgStoreBlendAlpha(ProgramStore.BLEND_ALPHA_DEPTH_NONE(mRS));
@@ -150,5 +165,7 @@
mFillScript.set_gTexOpaque(loadTextureRGB(R.drawable.data));
mFillScript.set_gTexTransparent(loadTextureARGB(R.drawable.leaf));
mFillScript.set_gTexChecker(loadTextureRGB(R.drawable.checker));
+
+ mFillScript.bind_gFragData(mFragData);
}
}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/fill_test.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/fill_test.rs
index 23832d3..281f830 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/fill_test.rs
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/fill_test.rs
@@ -21,6 +21,7 @@
rs_program_vertex gProgVertex;
rs_program_fragment gProgFragmentTexture;
+rs_program_fragment gProgFragmentTextureModulate;
rs_program_fragment gProgFragmentMultitex;
rs_program_store gProgStoreBlendNone;
@@ -41,6 +42,11 @@
} FillTestData;
FillTestData *gData;
+typedef struct FillTestFragData_s {
+ float4 modulate;
+} FillTestFragData;
+FillTestFragData *gFragData;
+
static float gDt = 0.0f;
void init() {
@@ -58,7 +64,7 @@
rsgProgramVertexLoadProjectionMatrix(&proj);
}
-static void displaySingletexFill(bool blend, int quadCount) {
+static void displaySingletexFill(bool blend, int quadCount, bool modulate) {
bindProgramVertexOrtho();
rs_matrix4x4 matrix;
rsMatrixLoadIdentity(&matrix);
@@ -70,9 +76,21 @@
} else {
rsgBindProgramStore(gProgStoreBlendAlpha);
}
- rsgBindProgramFragment(gProgFragmentTexture);
- rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
- rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque);
+ if (modulate) {
+ rsgBindProgramFragment(gProgFragmentTextureModulate);
+ rsgBindSampler(gProgFragmentTextureModulate, 0, gLinearClamp);
+ rsgBindTexture(gProgFragmentTextureModulate, 0, gTexOpaque);
+
+ gFragData->modulate.r = 0.8f;
+ gFragData->modulate.g = 0.7f;
+ gFragData->modulate.b = 0.8f;
+ gFragData->modulate.a = 0.5f;
+ rsgAllocationSyncAll(rsGetAllocation(gFragData));
+ } else {
+ rsgBindProgramFragment(gProgFragmentTexture);
+ rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+ rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque);
+ }
for (int i = 0; i < quadCount; i ++) {
float startX = 5 * i, startY = 5 * i;
@@ -128,7 +146,10 @@
displayMultitextureSample(gData->blend == 1 ? true : false, gData->quadCount);
break;
case 1:
- displaySingletexFill(gData->blend == 1 ? true : false, gData->quadCount);
+ displaySingletexFill(gData->blend == 1 ? true : false, gData->quadCount, false);
+ break;
+ case 2:
+ displaySingletexFill(gData->blend == 1 ? true : false, gData->quadCount, true);
break;
default:
rsDebug("Wrong test number", 0);
diff --git a/tests/RenderScriptTests/SceneGraph/Android.mk b/tests/RenderScriptTests/SceneGraph/Android.mk
new file mode 100644
index 0000000..ba4b3c5
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/Android.mk
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := SceneGraphTest
+
+include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/SceneGraph/AndroidManifest.xml b/tests/RenderScriptTests/SceneGraph/AndroidManifest.xml
new file mode 100644
index 0000000..e8d1e8e
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.testapp">
+ <uses-permission
+ android:name="android.permission.INTERNET" />
+ <application android:label="SceneGraphTest">
+ <activity android:name="TestApp"
+ android:label="SceneGraphTest">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name="FileSelector"
+ android:label="FileSelector"
+ android:hardwareAccelerated="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/RenderScriptTests/SceneGraph/assets/blue.jpg b/tests/RenderScriptTests/SceneGraph/assets/blue.jpg
new file mode 100644
index 0000000..494e77a
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/assets/blue.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/SceneGraph/assets/carbonfiber.jpg b/tests/RenderScriptTests/SceneGraph/assets/carbonfiber.jpg
new file mode 100644
index 0000000..2fcecb0
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/assets/carbonfiber.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/SceneGraph/assets/green.jpg b/tests/RenderScriptTests/SceneGraph/assets/green.jpg
new file mode 100644
index 0000000..a86a754
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/assets/green.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/SceneGraph/assets/grey.jpg b/tests/RenderScriptTests/SceneGraph/assets/grey.jpg
new file mode 100644
index 0000000..5870b1a
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/assets/grey.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/SceneGraph/assets/orange.jpg b/tests/RenderScriptTests/SceneGraph/assets/orange.jpg
new file mode 100644
index 0000000..7dbe942
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/assets/orange.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/SceneGraph/assets/orientation_test.a3d b/tests/RenderScriptTests/SceneGraph/assets/orientation_test.a3d
new file mode 100644
index 0000000..07318ae
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/assets/orientation_test.a3d
Binary files differ
diff --git a/tests/RenderScriptTests/SceneGraph/assets/orientation_test.dae b/tests/RenderScriptTests/SceneGraph/assets/orientation_test.dae
new file mode 100644
index 0000000..7eef443f
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/assets/orientation_test.dae
@@ -0,0 +1,1102 @@
+<?xml version="1.0" ?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+ <contributor>
+ <author>alexst</author>
+ <authoring_tool>OpenCOLLADA2010</authoring_tool>
+ <comments>ColladaMaya export options: bakeTransforms=0;relativePaths=0;copyTextures=0;exportTriangles=1;exportCgfxFileReferences=0; isSampling=0;curveConstrainSampling=0;removeStaticCurves=1;exportPolygonMeshes=1;exportLights=1; exportCameras=1;exportJointsAndSkin=1;exportAnimations=0;exportInvisibleNodes=0;exportDefaultCameras=0; exportTexCoords=1;exportNormals=1;exportNormalsPerVertex=1;exportVertexColors=0;exportVertexColorsPerVertex=0; exportTexTangents=0;exportTangents=0;exportReferencedMaterials=1;exportMaterialsOnly=0; exportXRefs=1;dereferenceXRefs=1;exportCameraAsLookat=0;cameraXFov=0;cameraYFov=1;doublePrecision=0</comments>
+ <source_data>file:///Volumes/Android/art/orientation_test.mb</source_data>
+ </contributor>
+ <created>2011-09-30T15:31:38</created>
+ <modified>2011-09-30T15:31:38</modified>
+ <unit meter="0.01" name="centimeter" />
+ <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_cameras>
+ <camera id="cameraShape1" name="cameraShape1">
+ <optics>
+ <technique_common>
+ <perspective>
+ <yfov>37.8493</yfov>
+ <aspect_ratio>1.5</aspect_ratio>
+ <znear>1</znear>
+ <zfar>400</zfar>
+ </perspective>
+ </technique_common>
+ </optics>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <film_fit>0</film_fit>
+ <film_fit_offset>0</film_fit_offset>
+ <film_offsetX>0</film_offsetX>
+ <film_offsetY>0</film_offsetY>
+ <horizontal_aperture>3.599993</horizontal_aperture>
+ <lens_squeeze>1</lens_squeeze>
+ <originalMayaNodeId>cameraShape1</originalMayaNodeId>
+ <vertical_aperture>2.399995</vertical_aperture>
+ </technique>
+ </extra>
+ </camera>
+ <camera id="CameraDistShape" name="CameraDistShape">
+ <optics>
+ <technique_common>
+ <perspective>
+ <yfov>37.8493</yfov>
+ <aspect_ratio>1.5</aspect_ratio>
+ <znear>1</znear>
+ <zfar>1000</zfar>
+ </perspective>
+ </technique_common>
+ </optics>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <film_fit>0</film_fit>
+ <film_fit_offset>0</film_fit_offset>
+ <film_offsetX>0</film_offsetX>
+ <film_offsetY>0</film_offsetY>
+ <horizontal_aperture>3.599993</horizontal_aperture>
+ <lens_squeeze>1</lens_squeeze>
+ <originalMayaNodeId>CameraDistShape</originalMayaNodeId>
+ <vertical_aperture>2.399995</vertical_aperture>
+ </technique>
+ </extra>
+ </camera>
+ </library_cameras>
+ <library_materials>
+ <material id="Paint1" name="Paint1">
+ <instance_effect url="#Paint1-fx" />
+ </material>
+ <material id="lambert2" name="lambert2">
+ <instance_effect url="#lambert2-fx" />
+ </material>
+ <material id="Plastic" name="Plastic">
+ <instance_effect url="#Plastic-fx" />
+ </material>
+ <material id="Metal" name="Metal">
+ <instance_effect url="#Metal-fx" />
+ </material>
+ <material id="PlasticCenter" name="PlasticCenter">
+ <instance_effect url="#PlasticCenter-fx" />
+ </material>
+ <material id="PlasticRed" name="PlasticRed">
+ <instance_effect url="#PlasticRed-fx" />
+ </material>
+ <material id="lambert10" name="lambert10">
+ <instance_effect url="#lambert10-fx" />
+ </material>
+ <material id="lambert11" name="lambert11">
+ <instance_effect url="#lambert11-fx" />
+ </material>
+ </library_materials>
+ <library_effects>
+ <effect id="Metal-fx">
+ <profile_COMMON>
+ <newparam sid="file23-surface">
+ <surface type="2D">
+ <init_from>file23</init_from>
+ </surface>
+ </newparam>
+ <newparam sid="file23-sampler">
+ <sampler2D>
+ <source>file23-surface</source>
+ </sampler2D>
+ </newparam>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <texture texture="file23-sampler" texcoord="TEX0">
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <blend_mode>NONE</blend_mode>
+ <coverageU>1</coverageU>
+ <coverageV>1</coverageV>
+ <fast>0</fast>
+ <mirrorU>0</mirrorU>
+ <mirrorV>0</mirrorV>
+ <noiseU>0</noiseU>
+ <noiseV>0</noiseV>
+ <offsetU>0</offsetU>
+ <offsetV>0</offsetV>
+ <repeatU>1</repeatU>
+ <repeatV>1</repeatV>
+ <rotateFrame>0</rotateFrame>
+ <rotateUV>0</rotateUV>
+ <stagger>0</stagger>
+ <translateFrameU>0</translateFrameU>
+ <translateFrameV>0</translateFrameV>
+ <wrapU>1</wrapU>
+ <wrapV>1</wrapV>
+ </technique>
+ </extra>
+ </texture>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ <effect id="Paint1-fx">
+ <profile_COMMON>
+ <newparam sid="file25-surface">
+ <surface type="2D">
+ <init_from>file25</init_from>
+ </surface>
+ </newparam>
+ <newparam sid="file25-sampler">
+ <sampler2D>
+ <source>file25-surface</source>
+ </sampler2D>
+ </newparam>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <texture texture="file25-sampler" texcoord="TEX0">
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <blend_mode>NONE</blend_mode>
+ <coverageU>1</coverageU>
+ <coverageV>1</coverageV>
+ <fast>0</fast>
+ <mirrorU>0</mirrorU>
+ <mirrorV>0</mirrorV>
+ <noiseU>0</noiseU>
+ <noiseV>0</noiseV>
+ <offsetU>0</offsetU>
+ <offsetV>0</offsetV>
+ <repeatU>1</repeatU>
+ <repeatV>1</repeatV>
+ <rotateFrame>0</rotateFrame>
+ <rotateUV>0</rotateUV>
+ <stagger>0</stagger>
+ <translateFrameU>0</translateFrameU>
+ <translateFrameV>0</translateFrameV>
+ <wrapU>1</wrapU>
+ <wrapV>1</wrapV>
+ </technique>
+ </extra>
+ </texture>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ <effect id="Plastic-fx">
+ <profile_COMMON>
+ <newparam sid="file24-surface">
+ <surface type="2D">
+ <init_from>file24</init_from>
+ </surface>
+ </newparam>
+ <newparam sid="file24-sampler">
+ <sampler2D>
+ <source>file24-surface</source>
+ </sampler2D>
+ </newparam>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <texture texture="file24-sampler" texcoord="TEX0">
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <blend_mode>NONE</blend_mode>
+ <coverageU>1</coverageU>
+ <coverageV>1</coverageV>
+ <fast>0</fast>
+ <mirrorU>0</mirrorU>
+ <mirrorV>0</mirrorV>
+ <noiseU>0</noiseU>
+ <noiseV>0</noiseV>
+ <offsetU>0</offsetU>
+ <offsetV>0</offsetV>
+ <repeatU>1</repeatU>
+ <repeatV>1</repeatV>
+ <rotateFrame>0</rotateFrame>
+ <rotateUV>0</rotateUV>
+ <stagger>0</stagger>
+ <translateFrameU>0</translateFrameU>
+ <translateFrameV>0</translateFrameV>
+ <wrapU>1</wrapU>
+ <wrapV>1</wrapV>
+ </technique>
+ </extra>
+ </texture>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ <effect id="PlasticCenter-fx">
+ <profile_COMMON>
+ <newparam sid="file24-surface">
+ <surface type="2D">
+ <init_from>file24</init_from>
+ </surface>
+ </newparam>
+ <newparam sid="file24-sampler">
+ <sampler2D>
+ <source>file24-surface</source>
+ </sampler2D>
+ </newparam>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <texture texture="file24-sampler" texcoord="TEX0">
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <blend_mode>NONE</blend_mode>
+ <coverageU>1</coverageU>
+ <coverageV>1</coverageV>
+ <fast>0</fast>
+ <mirrorU>0</mirrorU>
+ <mirrorV>0</mirrorV>
+ <noiseU>0</noiseU>
+ <noiseV>0</noiseV>
+ <offsetU>0</offsetU>
+ <offsetV>0</offsetV>
+ <repeatU>1</repeatU>
+ <repeatV>1</repeatV>
+ <rotateFrame>0</rotateFrame>
+ <rotateUV>0</rotateUV>
+ <stagger>0</stagger>
+ <translateFrameU>0</translateFrameU>
+ <translateFrameV>0</translateFrameV>
+ <wrapU>1</wrapU>
+ <wrapV>1</wrapV>
+ </technique>
+ </extra>
+ </texture>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ <effect id="PlasticRed-fx">
+ <profile_COMMON>
+ <newparam sid="file23-surface">
+ <surface type="2D">
+ <init_from>file23</init_from>
+ </surface>
+ </newparam>
+ <newparam sid="file23-sampler">
+ <sampler2D>
+ <source>file23-surface</source>
+ </sampler2D>
+ </newparam>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <texture texture="file23-sampler" texcoord="TEX0">
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <blend_mode>NONE</blend_mode>
+ <coverageU>1</coverageU>
+ <coverageV>1</coverageV>
+ <fast>0</fast>
+ <mirrorU>0</mirrorU>
+ <mirrorV>0</mirrorV>
+ <noiseU>0</noiseU>
+ <noiseV>0</noiseV>
+ <offsetU>0</offsetU>
+ <offsetV>0</offsetV>
+ <repeatU>1</repeatU>
+ <repeatV>1</repeatV>
+ <rotateFrame>0</rotateFrame>
+ <rotateUV>0</rotateUV>
+ <stagger>0</stagger>
+ <translateFrameU>0</translateFrameU>
+ <translateFrameV>0</translateFrameV>
+ <wrapU>1</wrapU>
+ <wrapV>1</wrapV>
+ </technique>
+ </extra>
+ </texture>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ <effect id="lambert10-fx">
+ <profile_COMMON>
+ <newparam sid="file28-surface">
+ <surface type="2D">
+ <init_from>file28</init_from>
+ </surface>
+ </newparam>
+ <newparam sid="file28-sampler">
+ <sampler2D>
+ <source>file28-surface</source>
+ </sampler2D>
+ </newparam>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <texture texture="file28-sampler" texcoord="TEX0">
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <blend_mode>NONE</blend_mode>
+ <coverageU>1</coverageU>
+ <coverageV>1</coverageV>
+ <fast>0</fast>
+ <mirrorU>0</mirrorU>
+ <mirrorV>0</mirrorV>
+ <noiseU>0</noiseU>
+ <noiseV>0</noiseV>
+ <offsetU>0</offsetU>
+ <offsetV>0</offsetV>
+ <repeatU>1</repeatU>
+ <repeatV>1</repeatV>
+ <rotateFrame>0</rotateFrame>
+ <rotateUV>0</rotateUV>
+ <stagger>0</stagger>
+ <translateFrameU>0</translateFrameU>
+ <translateFrameV>0</translateFrameV>
+ <wrapU>1</wrapU>
+ <wrapV>1</wrapV>
+ </technique>
+ </extra>
+ </texture>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ <effect id="lambert11-fx">
+ <profile_COMMON>
+ <newparam sid="file29-surface">
+ <surface type="2D">
+ <init_from>file29</init_from>
+ </surface>
+ </newparam>
+ <newparam sid="file29-sampler">
+ <sampler2D>
+ <source>file29-surface</source>
+ </sampler2D>
+ </newparam>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <texture texture="file29-sampler" texcoord="TEX0">
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <blend_mode>NONE</blend_mode>
+ <coverageU>1</coverageU>
+ <coverageV>1</coverageV>
+ <fast>0</fast>
+ <mirrorU>0</mirrorU>
+ <mirrorV>0</mirrorV>
+ <noiseU>0</noiseU>
+ <noiseV>0</noiseV>
+ <offsetU>0</offsetU>
+ <offsetV>0</offsetV>
+ <repeatU>1</repeatU>
+ <repeatV>1</repeatV>
+ <rotateFrame>0</rotateFrame>
+ <rotateUV>0</rotateUV>
+ <stagger>0</stagger>
+ <translateFrameU>0</translateFrameU>
+ <translateFrameV>0</translateFrameV>
+ <wrapU>1</wrapU>
+ <wrapV>1</wrapV>
+ </technique>
+ </extra>
+ </texture>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ <effect id="lambert2-fx">
+ <profile_COMMON>
+ <newparam sid="file22-surface">
+ <surface type="2D">
+ <init_from>file22</init_from>
+ </surface>
+ </newparam>
+ <newparam sid="file22-sampler">
+ <sampler2D>
+ <source>file22-surface</source>
+ </sampler2D>
+ </newparam>
+ <technique sid="common">
+ <lambert>
+ <emission>
+ <color>0 0 0 1</color>
+ </emission>
+ <ambient>
+ <color>0 0 0 1</color>
+ </ambient>
+ <diffuse>
+ <texture texture="file22-sampler" texcoord="TEX0">
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <blend_mode>NONE</blend_mode>
+ <coverageU>1</coverageU>
+ <coverageV>1</coverageV>
+ <fast>0</fast>
+ <mirrorU>0</mirrorU>
+ <mirrorV>0</mirrorV>
+ <noiseU>0</noiseU>
+ <noiseV>0</noiseV>
+ <offsetU>0</offsetU>
+ <offsetV>0</offsetV>
+ <repeatU>1</repeatU>
+ <repeatV>1</repeatV>
+ <rotateFrame>0</rotateFrame>
+ <rotateUV>0</rotateUV>
+ <stagger>0</stagger>
+ <translateFrameU>0</translateFrameU>
+ <translateFrameV>0</translateFrameV>
+ <wrapU>1</wrapU>
+ <wrapV>1</wrapV>
+ </technique>
+ </extra>
+ </texture>
+ </diffuse>
+ <transparent opaque="RGB_ZERO">
+ <color>0 0 0 1</color>
+ </transparent>
+ <transparency>
+ <float>1</float>
+ </transparency>
+ </lambert>
+ </technique>
+ </profile_COMMON>
+ </effect>
+ </library_effects>
+ <library_images>
+ <image id="file29" name="file29" height="0" width="0">
+ <init_from>file:///Volumes/Android/Sanity/SceneGraph/assets/blue.jpg</init_from>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <dgnode_type>kFile</dgnode_type>
+ <image_sequence>0</image_sequence>
+ <originalMayaNodeId>file29</originalMayaNodeId>
+ </technique>
+ </extra>
+ </image>
+ <image id="file25" name="file25" height="0" width="0">
+ <init_from>file:///Volumes/Android/Sanity/SceneGraph/assets/carbonfiber.jpg</init_from>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <dgnode_type>kFile</dgnode_type>
+ <image_sequence>0</image_sequence>
+ <originalMayaNodeId>file25</originalMayaNodeId>
+ </technique>
+ </extra>
+ </image>
+ <image id="file28" name="file28" height="0" width="0">
+ <init_from>file:///Volumes/Android/Sanity/SceneGraph/assets/green.jpg</init_from>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <dgnode_type>kFile</dgnode_type>
+ <image_sequence>0</image_sequence>
+ <originalMayaNodeId>file28</originalMayaNodeId>
+ </technique>
+ </extra>
+ </image>
+ <image id="file22" name="file22" height="0" width="0">
+ <init_from>file:///Volumes/Android/Sanity/SceneGraph/assets/grey.jpg</init_from>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <dgnode_type>kFile</dgnode_type>
+ <image_sequence>0</image_sequence>
+ <originalMayaNodeId>file22</originalMayaNodeId>
+ </technique>
+ </extra>
+ </image>
+ <image id="file24" name="file24" height="0" width="0">
+ <init_from>file:///Volumes/Android/Sanity/SceneGraph/assets/orange.jpg</init_from>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <dgnode_type>kFile</dgnode_type>
+ <image_sequence>0</image_sequence>
+ <originalMayaNodeId>file24</originalMayaNodeId>
+ </technique>
+ </extra>
+ </image>
+ <image id="file23" name="file23" height="0" width="0">
+ <init_from>file:///Volumes/Android/Sanity/SceneGraph/assets/red.jpg</init_from>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <dgnode_type>kFile</dgnode_type>
+ <image_sequence>0</image_sequence>
+ <originalMayaNodeId>file23</originalMayaNodeId>
+ </technique>
+ </extra>
+ </image>
+ </library_images>
+ <library_visual_scenes>
+ <visual_scene id="VisualSceneNode" name="orientation_test">
+ <node id="camera1" name="camera1">
+ <translate sid="translate">24.5791 14.1321 31.4654</translate>
+ <rotate sid="rotateZ">0 0 1 0</rotate>
+ <rotate sid="rotateY">0 1 0 42</rotate>
+ <rotate sid="rotateX">1 0 0 -16.2</rotate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_camera url="#cameraShape1" />
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>camera1</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="CameraAim" name="CameraAim">
+ <translate sid="translate">0.0209301 3.68542 2.06912</translate>
+ <rotate sid="rotateY">0 1 0 43.2561</rotate>
+ <rotate sid="rotateX">1 0 0 -20</rotate>
+ <scale sid="scale">1 1 1</scale>
+ <node id="CameraDist" name="CameraDist">
+ <translate sid="translate">0 0 45</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_camera url="#CameraDistShape" />
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>CameraDist</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>CameraAim</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pSphere4" name="pSphere4">
+ <translate sid="translate">-9.69237 0 7.70498</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pSphereShape4">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert7SG" target="#Paint1">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pSphere4</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pSphere1" name="pSphere1">
+ <translate sid="translate">13.0966 0 5.76254</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pSphereShape1">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert7SG" target="#Paint1">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pSphere1</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pSphere2" name="pSphere2">
+ <translate sid="translate">21.7661 0 -13.6375</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pSphereShape2">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert7SG" target="#Paint1">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pSphere2</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pSphere3" name="pSphere3">
+ <translate sid="translate">-13.862 0 -13.6154</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pSphereShape3">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert7SG" target="#Paint1">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pSphere3</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pSphere5" name="pSphere5">
+ <translate sid="translate">31.0862 0 18.5992</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pSphereShape5">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert7SG" target="#Paint1">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pSphere5</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pCube1" name="pCube1">
+ <translate sid="translate">0 0 0</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pCubeShape1">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert4SG" target="#lambert2">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pCube1</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="group1" name="group1">
+ <translate sid="translate">0 0 0</translate>
+ <rotate sid="rotateZ">0 0 1 -162.693</rotate>
+ <rotate sid="rotateY">0 1 0 21.3345</rotate>
+ <rotate sid="rotateX">1 0 0 -100.567</rotate>
+ <scale sid="scale">1 1 1</scale>
+ <node id="pSphere6" name="pSphere6">
+ <translate sid="translate">-13.862 0 -13.6154</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pSphereShape6">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert6SG" target="#Plastic">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pSphere6</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pSphere7" name="pSphere7">
+ <translate sid="translate">-9.69237 0 7.70498</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pSphereShape7">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert6SG" target="#Plastic">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pSphere7</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pSphere8" name="pSphere8">
+ <translate sid="translate">21.7661 0 -13.6375</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pSphereShape8">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert6SG" target="#Plastic">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pSphere8</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pSphere9" name="pSphere9">
+ <translate sid="translate">13.0966 0 5.76254</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pSphereShape9">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert6SG" target="#Plastic">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pSphere9</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>group1</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="group2" name="group2">
+ <translate sid="translate">0 0 0</translate>
+ <rotate sid="rotateZ">0 0 1 45.4017</rotate>
+ <rotate sid="rotateY">0 1 0 79.393</rotate>
+ <rotate sid="rotateX">1 0 0 5.10889</rotate>
+ <scale sid="scale">1 1 1</scale>
+ <node id="pSphere10" name="pSphere10">
+ <translate sid="translate">31.0862 0 18.5992</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pSphereShape10">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert5SG" target="#Metal">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pSphere10</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pSphere11" name="pSphere11">
+ <translate sid="translate">13.0966 0 5.76254</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pSphereShape11">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert5SG" target="#Metal">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pSphere11</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pSphere12" name="pSphere12">
+ <translate sid="translate">7.4784 16.3496 7.36882</translate>
+ <rotate sid="rotateZ">0 0 1 17.3073</rotate>
+ <rotate sid="rotateY">0 1 0 158.666</rotate>
+ <rotate sid="rotateX">1 0 0 79.4335</rotate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pSphereShape12">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert5SG" target="#Metal">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pSphere12</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pSphere13" name="pSphere13">
+ <translate sid="translate">-9.69237 0 7.70498</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pSphereShape13">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert5SG" target="#Metal">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pSphere13</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pSphere14" name="pSphere14">
+ <translate sid="translate">11.3635 -4.3926 2.21012</translate>
+ <rotate sid="rotateZ">0 0 1 17.3073</rotate>
+ <rotate sid="rotateY">0 1 0 158.666</rotate>
+ <rotate sid="rotateX">1 0 0 79.4335</rotate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pSphereShape14">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert5SG" target="#Metal">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pSphere14</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pSphere15" name="pSphere15">
+ <translate sid="translate">21.7661 0 -13.6375</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pSphereShape15">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert5SG" target="#Metal">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pSphere15</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pSphere16" name="pSphere16">
+ <translate sid="translate">-9.5945 -8.92317 -5.74901</translate>
+ <rotate sid="rotateZ">0 0 1 17.3073</rotate>
+ <rotate sid="rotateY">0 1 0 158.666</rotate>
+ <rotate sid="rotateX">1 0 0 79.4335</rotate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pSphereShape16">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert5SG" target="#Metal">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pSphere16</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pSphere17" name="pSphere17">
+ <translate sid="translate">-13.862 0 -13.6154</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pSphereShape17">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert5SG" target="#Metal">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pSphere17</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pSphere18" name="pSphere18">
+ <translate sid="translate">-24.2135 6.497 -5.58935</translate>
+ <rotate sid="rotateZ">0 0 1 17.3073</rotate>
+ <rotate sid="rotateY">0 1 0 158.666</rotate>
+ <rotate sid="rotateX">1 0 0 79.4335</rotate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pSphereShape18">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert5SG" target="#Metal">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pSphere18</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>group2</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pCube2" name="pCube2">
+ <translate sid="translate">0 0 0</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pCubeShape2">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert8SG" target="#PlasticCenter">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pCube2</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pCube3" name="pCube3">
+ <translate sid="translate">15 0 0</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pCubeShape3">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert9SG" target="#PlasticRed">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pCube3</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pCube4" name="pCube4">
+ <translate sid="translate">0 15 0</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pCubeShape4">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert10SG" target="#lambert10">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pCube4</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ <node id="pCube5" name="pCube5">
+ <translate sid="translate">0 0 15</translate>
+ <scale sid="scale">1 1 1</scale>
+ <instance_geometry url="#pCubeShape5">
+ <bind_material>
+ <technique_common>
+ <instance_material symbol="lambert11SG" target="#lambert11">
+ <bind_vertex_input semantic="TEX0" input_semantic="TEXCOORD" input_set="0" />
+ </instance_material>
+ </technique_common>
+ </bind_material>
+ </instance_geometry>
+ <extra>
+ <technique profile="OpenCOLLADAMaya">
+ <originalMayaNodeId>pCube5</originalMayaNodeId>
+ </technique>
+ </extra>
+ </node>
+ </visual_scene>
+ </library_visual_scenes>
+ <scene>
+ <instance_visual_scene url="#VisualSceneNode" />
+ </scene>
+</COLLADA>
diff --git a/tests/RenderScriptTests/SceneGraph/assets/paint.jpg b/tests/RenderScriptTests/SceneGraph/assets/paint.jpg
new file mode 100644
index 0000000..0791045
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/assets/paint.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/SceneGraph/assets/red.jpg b/tests/RenderScriptTests/SceneGraph/assets/red.jpg
new file mode 100644
index 0000000..320a2a6
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/assets/red.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/SceneGraph/res/drawable-nodpi/robot.png b/tests/RenderScriptTests/SceneGraph/res/drawable-nodpi/robot.png
new file mode 100644
index 0000000..f7353fd
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/res/drawable-nodpi/robot.png
Binary files differ
diff --git a/tests/RenderScriptTests/SceneGraph/res/menu/loader_menu.xml b/tests/RenderScriptTests/SceneGraph/res/menu/loader_menu.xml
new file mode 100644
index 0000000..9ea30107
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/res/menu/loader_menu.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2011 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/load_model"
+ android:title="@string/load_model" />
+ <item android:id="@+id/use_blur"
+ android:title="@string/use_blur" />
+</menu>
diff --git a/tests/RenderScriptTests/SceneGraph/res/raw/blur_h.glsl b/tests/RenderScriptTests/SceneGraph/res/raw/blur_h.glsl
new file mode 100644
index 0000000..fa468cc
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/res/raw/blur_h.glsl
@@ -0,0 +1,15 @@
+varying vec2 varTex0;
+
+void main() {
+ vec2 blurCoord = varTex0;
+ blurCoord.x = varTex0.x + UNI_blurOffset0;
+ vec3 col = texture2D(UNI_Tex0, blurCoord).rgb;
+ blurCoord.x = varTex0.x + UNI_blurOffset1;
+ col += texture2D(UNI_Tex0, blurCoord).rgb;
+ blurCoord.x = varTex0.x + UNI_blurOffset2;
+ col += texture2D(UNI_Tex0, blurCoord).rgb;
+ blurCoord.x = varTex0.x + UNI_blurOffset3;
+ col += texture2D(UNI_Tex0, blurCoord).rgb;
+
+ gl_FragColor = vec4(col * 0.25, 0.0); //texture2D(UNI_Tex0, varTex0);
+}
diff --git a/tests/RenderScriptTests/SceneGraph/res/raw/blur_v.glsl b/tests/RenderScriptTests/SceneGraph/res/raw/blur_v.glsl
new file mode 100644
index 0000000..a644a3e
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/res/raw/blur_v.glsl
@@ -0,0 +1,17 @@
+varying vec2 varTex0;
+
+void main() {
+ vec2 blurCoord = varTex0;
+ blurCoord.y = varTex0.y + UNI_blurOffset0;
+ vec3 col = texture2D(UNI_Tex0, blurCoord).rgb;
+ blurCoord.y = varTex0.y + UNI_blurOffset1;
+ col += texture2D(UNI_Tex0, blurCoord).rgb;
+ blurCoord.y = varTex0.y + UNI_blurOffset2;
+ col += texture2D(UNI_Tex0, blurCoord).rgb;
+ blurCoord.y = varTex0.y + UNI_blurOffset3;
+ col += texture2D(UNI_Tex0, blurCoord).rgb;
+
+ col = col * 0.25;
+
+ gl_FragColor = vec4(col, 0.0); //texture2D(UNI_Tex0, varTex0);
+}
diff --git a/tests/RenderScriptTests/SceneGraph/res/raw/blur_vertex.glsl b/tests/RenderScriptTests/SceneGraph/res/raw/blur_vertex.glsl
new file mode 100644
index 0000000..bc824b6
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/res/raw/blur_vertex.glsl
@@ -0,0 +1,7 @@
+varying vec2 varTex0;
+
+void main() {
+ gl_Position = ATTRIB_position;
+ varTex0 = ATTRIB_texture0;
+}
+
diff --git a/tests/RenderScriptTests/SceneGraph/res/raw/diffuse.glsl b/tests/RenderScriptTests/SceneGraph/res/raw/diffuse.glsl
new file mode 100644
index 0000000..5d8938b
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/res/raw/diffuse.glsl
@@ -0,0 +1,19 @@
+varying vec3 varWorldPos;
+varying vec3 varWorldNormal;
+varying vec2 varTex0;
+
+void main() {
+
+ vec3 V = normalize(UNI_cameraPos.xyz - varWorldPos.xyz);
+ vec3 worldNorm = (varWorldNormal);
+
+ vec3 light0Vec = V;
+ vec3 light0R = reflect(light0Vec, worldNorm);
+ float light0_Diffuse = dot(worldNorm, light0Vec);
+
+ vec2 t0 = varTex0.xy;
+ lowp vec4 col = texture2D(UNI_Tex0, t0).rgba;
+ col.xyz = col.xyz * light0_Diffuse * 1.2;
+ gl_FragColor = col; //vec4(0.0, 1.0, 0.0, 0.0);
+}
+
diff --git a/tests/RenderScriptTests/SceneGraph/res/raw/metal.glsl b/tests/RenderScriptTests/SceneGraph/res/raw/metal.glsl
new file mode 100644
index 0000000..51f0612
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/res/raw/metal.glsl
@@ -0,0 +1,23 @@
+varying vec3 varWorldPos;
+varying vec3 varWorldNormal;
+varying vec2 varTex0;
+
+void main() {
+
+ vec3 V = normalize(UNI_cameraPos.xyz - varWorldPos.xyz);
+ vec3 worldNorm = normalize(varWorldNormal);
+
+ vec3 light0Vec = V;
+ vec3 light0R = reflect(light0Vec, worldNorm);
+ float light0_Diffuse = clamp(dot(worldNorm, light0Vec), 0.0, 1.0);
+ float light0Spec = clamp(dot(-light0R, V), 0.001, 1.0);
+ float light0_Specular = pow(light0Spec, 15.0) * 0.5;
+
+ vec2 t0 = varTex0.xy;
+ lowp vec4 col = texture2D(UNI_Tex0, t0).rgba;
+ col.xyz = col.xyz * (textureCube(UNI_Tex1, worldNorm).rgb * 0.5 + vec3(light0_Diffuse));
+ col.xyz += light0_Specular * vec3(0.8, 0.8, 1.0);
+
+ gl_FragColor = col;
+}
+
diff --git a/tests/RenderScriptTests/SceneGraph/res/raw/paintf.glsl b/tests/RenderScriptTests/SceneGraph/res/raw/paintf.glsl
new file mode 100644
index 0000000..893d553
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/res/raw/paintf.glsl
@@ -0,0 +1,26 @@
+varying vec3 varWorldPos;
+varying vec3 varWorldNormal;
+varying vec2 varTex0;
+
+void main() {
+
+ vec3 V = normalize(UNI_cameraPos.xyz - varWorldPos.xyz);
+ vec3 worldNorm = normalize(varWorldNormal);
+
+ vec3 light0Vec = V;
+ vec3 light0R = reflect(light0Vec, worldNorm);
+ float light0_Diffuse = clamp(dot(worldNorm, light0Vec), 0.01, 0.99);
+ float light0Spec = clamp(dot(-light0R, V), 0.001, 1.0);
+ float light0_Specular = pow(light0Spec, 150.0) * 0.5;
+
+ vec2 t0 = varTex0.xy;
+ lowp vec4 col = texture2D(UNI_Tex0, t0).rgba;
+ col.xyz = col.xyz * light0_Diffuse * 1.1;
+ col.xyz += light0_Specular * vec3(0.8, 0.8, 1.0);
+
+ float fresnel = mix(pow(1.0 - light0_Diffuse, 15.0), 1.0, 0.1);
+ col.xyz = mix(col.xyz, textureCube(UNI_Tex1, -light0R).rgb * 2.4, fresnel);
+ col.w = 0.8;
+ gl_FragColor = col;
+}
+
diff --git a/tests/RenderScriptTests/SceneGraph/res/raw/plastic.glsl b/tests/RenderScriptTests/SceneGraph/res/raw/plastic.glsl
new file mode 100644
index 0000000..ceb53bd
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/res/raw/plastic.glsl
@@ -0,0 +1,22 @@
+varying vec3 varWorldPos;
+varying vec3 varWorldNormal;
+varying vec2 varTex0;
+
+void main() {
+
+ vec3 V = normalize(UNI_cameraPos.xyz - varWorldPos.xyz);
+ vec3 worldNorm = normalize(varWorldNormal);
+
+ vec3 light0Vec = V;
+ vec3 light0R = reflect(light0Vec, worldNorm);
+ float light0_Diffuse = clamp(dot(worldNorm, light0Vec), 0.0, 1.0);
+ float light0Spec = clamp(dot(-light0R, V), 0.001, 1.0);
+ float light0_Specular = pow(light0Spec, 10.0) * 0.5;
+
+ vec2 t0 = varTex0.xy;
+ lowp vec4 col = texture2D(UNI_Tex0, t0).rgba;
+ col.xyz = col.xyz * light0_Diffuse * 1.2;
+ col.xyz += light0_Specular * vec3(0.8, 0.8, 1.0);
+ gl_FragColor = col;
+}
+
diff --git a/tests/RenderScriptTests/SceneGraph/res/raw/plastic_lights.glsl b/tests/RenderScriptTests/SceneGraph/res/raw/plastic_lights.glsl
new file mode 100644
index 0000000..b253622
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/res/raw/plastic_lights.glsl
@@ -0,0 +1,29 @@
+varying vec3 varWorldPos;
+varying vec3 varWorldNormal;
+varying vec2 varTex0;
+
+void main() {
+
+ vec3 V = normalize(UNI_cameraPos.xyz - varWorldPos.xyz);
+ vec3 worldNorm = normalize(varWorldNormal);
+
+ vec3 light0Vec = normalize(UNI_lightPos_0.xyz - varWorldPos.xyz);
+ vec3 light0R = reflect(light0Vec, worldNorm);
+ float light0_Diffuse = clamp(dot(worldNorm, light0Vec), 0.0, 1.0);
+ float light0Spec = clamp(dot(-light0R, V), 0.001, 1.0);
+ float light0_Specular = pow(light0Spec, 10.0) * 0.7;
+
+ vec3 light1Vec = normalize(UNI_lightPos_1.xyz - varWorldPos.xyz);
+ vec3 light1R = reflect(light1Vec, worldNorm);
+ float light1_Diffuse = clamp(dot(worldNorm, light1Vec), 0.0, 1.0);
+ float light1Spec = clamp(dot(-light1R, V), 0.001, 1.0);
+ float light1_Specular = pow(light1Spec, 10.0) * 0.7;
+
+ vec2 t0 = varTex0.xy;
+ lowp vec4 col = UNI_diffuse;
+ col.xyz = col.xyz * (light0_Diffuse * UNI_lightColor_0.xyz +
+ light1_Diffuse * UNI_lightColor_1.xyz);
+ col.xyz += (light0_Specular + light1_Specular);
+ gl_FragColor = col;
+}
+
diff --git a/tests/RenderScriptTests/SceneGraph/res/raw/robot.a3d b/tests/RenderScriptTests/SceneGraph/res/raw/robot.a3d
new file mode 100644
index 0000000..f48895c
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/res/raw/robot.a3d
Binary files differ
diff --git a/tests/RenderScriptTests/SceneGraph/res/raw/select_color.glsl b/tests/RenderScriptTests/SceneGraph/res/raw/select_color.glsl
new file mode 100644
index 0000000..42b231a
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/res/raw/select_color.glsl
@@ -0,0 +1,13 @@
+varying vec2 varTex0;
+
+void main() {
+ vec3 col = texture2D(UNI_Tex0, varTex0).rgb;
+
+ vec3 desat = vec3(0.299, 0.587, 0.114);
+ float lum = dot(desat, col);
+ float stepVal = step(lum, 0.8);
+ col = mix(col, vec3(0.0), stepVal)*0.5;
+
+ gl_FragColor = vec4(col, 0.0);
+}
+
diff --git a/tests/RenderScriptTests/SceneGraph/res/raw/shader2v.glsl b/tests/RenderScriptTests/SceneGraph/res/raw/shader2v.glsl
new file mode 100644
index 0000000..1ea234f
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/res/raw/shader2v.glsl
@@ -0,0 +1,17 @@
+varying vec3 varWorldPos;
+varying vec3 varWorldNormal;
+varying vec2 varTex0;
+
+// This is where actual shader code begins
+void main() {
+ vec4 objPos = ATTRIB_position;
+ vec4 worldPos = UNI_model * objPos;
+ gl_Position = UNI_viewProj * worldPos;
+
+ mat3 model3 = mat3(UNI_model[0].xyz, UNI_model[1].xyz, UNI_model[2].xyz);
+ vec3 worldNorm = model3 * ATTRIB_normal;
+
+ varWorldPos = worldPos.xyz;
+ varWorldNormal = worldNorm;
+ varTex0 = ATTRIB_texture0;
+}
diff --git a/tests/RenderScriptTests/SceneGraph/res/raw/texture.glsl b/tests/RenderScriptTests/SceneGraph/res/raw/texture.glsl
new file mode 100644
index 0000000..dd709cf
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/res/raw/texture.glsl
@@ -0,0 +1,7 @@
+varying vec2 varTex0;
+
+void main() {
+ lowp vec4 col = texture2D(UNI_Tex0, varTex0).rgba;
+ gl_FragColor = col;
+}
+
diff --git a/tests/RenderScriptTests/SceneGraph/res/values/strings.xml b/tests/RenderScriptTests/SceneGraph/res/values/strings.xml
new file mode 100644
index 0000000..c916d79
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2011 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <skip />
+ <string name="load_model">Load Model</string>
+ <string name="use_blur">Use Blur</string>
+</resources>
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Camera.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Camera.java
new file mode 100644
index 0000000..42f2be5
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Camera.java
@@ -0,0 +1,118 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+
+import com.android.scenegraph.SceneManager;
+
+import android.renderscript.*;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScriptGL;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class Camera extends SceneGraphBase {
+
+ Transform mTransform;
+
+ ScriptField_Camera_s.Item mData;
+ ScriptField_Camera_s mField;
+
+ public Camera() {
+ mData = new ScriptField_Camera_s.Item();
+ mData.near = 0.1f;
+ mData.far = 1000.0f;
+ mData.horizontalFOV = 60.0f;
+ mData.aspect = 0;
+ }
+
+ public void setTransform(Transform t) {
+ mTransform = t;
+ if (mField != null) {
+ mField.set_transformMatrix(0, mTransform.getRSData().getAllocation(), true);
+ mField.set_isDirty(0, 1, true);
+ }
+ }
+ public void setFOV(float fov) {
+ mData.horizontalFOV = fov;
+ if (mField != null) {
+ mField.set_horizontalFOV(0, fov, true);
+ mField.set_isDirty(0, 1, true);
+ }
+ }
+
+ public void setNear(float n) {
+ mData.near = n;
+ if (mField != null) {
+ mField.set_near(0, n, true);
+ mField.set_isDirty(0, 1, true);
+ }
+ }
+
+ public void setFar(float f) {
+ mData.far = f;
+ if (mField != null) {
+ mField.set_far(0, f, true);
+ mField.set_isDirty(0, 1, true);
+ }
+ }
+
+ public void setName(String n) {
+ super.setName(n);
+ if (mField != null) {
+ RenderScriptGL rs = SceneManager.getRS();
+ mData.name = getNameAlloc(rs);
+ mField.set_name(0, mData.name, true);
+ mField.set_isDirty(0, 1, true);
+ }
+ }
+
+ ScriptField_Camera_s getRSData() {
+ if (mField != null) {
+ return mField;
+ }
+
+ RenderScriptGL rs = SceneManager.getRS();
+ if (rs == null) {
+ return null;
+ }
+
+ if (mTransform == null) {
+ throw new RuntimeException("Cameras without transforms are invalid");
+ }
+
+ mField = new ScriptField_Camera_s(rs, 1);
+
+ mData.transformMatrix = mTransform.getRSData().getAllocation();
+ mData.transformTimestamp = 1;
+ mData.timestamp = 1;
+ mData.isDirty = 1;
+ mData.name = getNameAlloc(rs);
+ mField.set(mData, 0, true);
+
+ return mField;
+ }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ColladaParser.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ColladaParser.java
new file mode 100644
index 0000000..d954313
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ColladaParser.java
@@ -0,0 +1,563 @@
+/*
+ * 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.scenegraph;
+import com.android.scenegraph.CompoundTransform.TranslateComponent;
+import com.android.scenegraph.CompoundTransform.RotateComponent;
+import com.android.scenegraph.CompoundTransform.ScaleComponent;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.HashMap;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import android.renderscript.*;
+import android.util.Log;
+
+public class ColladaParser {
+ static final String TAG = "ColladaParser";
+ Document mDom;
+
+ HashMap<String, LightBase> mLights;
+ HashMap<String, Camera> mCameras;
+ HashMap<String, ArrayList<ShaderParam> > mEffectsParams;
+ HashMap<String, Texture2D> mImages;
+ HashMap<String, Texture2D> mSamplerImageMap;
+ HashMap<String, String> mMeshIdNameMap;
+ Scene mScene;
+
+ String mRootDir;
+
+ String toString(Float3 v) {
+ String valueStr = v.x + " " + v.y + " " + v.z;
+ return valueStr;
+ }
+
+ String toString(Float4 v) {
+ String valueStr = v.x + " " + v.y + " " + v.z + " " + v.w;
+ return valueStr;
+ }
+
+ public ColladaParser(){
+ mLights = new HashMap<String, LightBase>();
+ mCameras = new HashMap<String, Camera>();
+ mEffectsParams = new HashMap<String, ArrayList<ShaderParam> >();
+ mImages = new HashMap<String, Texture2D>();
+ mMeshIdNameMap = new HashMap<String, String>();
+ }
+
+ public void init(InputStream is, String rootDir) {
+ mLights.clear();
+ mCameras.clear();
+ mEffectsParams.clear();
+
+ mRootDir = rootDir;
+
+ long start = System.currentTimeMillis();
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ try {
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ mDom = db.parse(is);
+ } catch(ParserConfigurationException e) {
+ e.printStackTrace();
+ } catch(SAXException e) {
+ e.printStackTrace();
+ } catch(IOException e) {
+ e.printStackTrace();
+ }
+ long end = System.currentTimeMillis();
+ Log.v("TIMER", " Parse time: " + (end - start));
+ exportSceneData();
+ }
+
+ Scene getScene() {
+ return mScene;
+ }
+
+ private void exportSceneData(){
+ mScene = new Scene();
+
+ Element docEle = mDom.getDocumentElement();
+ NodeList nl = docEle.getElementsByTagName("light");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element l = (Element)nl.item(i);
+ convertLight(l);
+ }
+ }
+
+ nl = docEle.getElementsByTagName("camera");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element c = (Element)nl.item(i);
+ convertCamera(c);
+ }
+ }
+
+ nl = docEle.getElementsByTagName("image");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element img = (Element)nl.item(i);
+ convertImage(img);
+ }
+ }
+
+ nl = docEle.getElementsByTagName("effect");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element e = (Element)nl.item(i);
+ convertEffects(e);
+ }
+ }
+
+ // Material is just a link to the effect
+ nl = docEle.getElementsByTagName("material");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element m = (Element)nl.item(i);
+ convertMaterials(m);
+ }
+ }
+
+ // Look through the geometry list and build up a correlation between id's and names
+ nl = docEle.getElementsByTagName("geometry");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element m = (Element)nl.item(i);
+ convertGeometries(m);
+ }
+ }
+
+
+ nl = docEle.getElementsByTagName("visual_scene");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element s = (Element)nl.item(i);
+ getScene(s);
+ }
+ }
+ }
+
+ private void getRenderable(Element shape, Transform t) {
+ String geoURL = shape.getAttribute("url").substring(1);
+ String geoName = mMeshIdNameMap.get(geoURL);
+ if (geoName != null) {
+ geoURL = geoName;
+ }
+ //RenderableGroup group = new RenderableGroup();
+ //group.setName(geoURL.substring(1));
+ //mScene.appendRenderable(group);
+ NodeList nl = shape.getElementsByTagName("instance_material");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element materialRef = (Element)nl.item(i);
+ String meshIndexName = materialRef.getAttribute("symbol");
+ String materialName = materialRef.getAttribute("target");
+
+ Renderable d = new Renderable();
+ d.setMesh(geoURL, meshIndexName);
+ d.setMaterialName(materialName.substring(1));
+ d.setName(geoURL);
+
+ //Log.v(TAG, "Created drawable geo " + geoURL + " index " + meshIndexName + " material " + materialName);
+
+ d.setTransform(t);
+ //Log.v(TAG, "Set source param " + t.getName());
+
+ // Now find all the parameters that exist on the material
+ ArrayList<ShaderParam> materialParams;
+ materialParams = mEffectsParams.get(materialName.substring(1));
+ for (int pI = 0; pI < materialParams.size(); pI ++) {
+ d.appendSourceParams(materialParams.get(pI));
+ //Log.v(TAG, "Set source param i: " + pI + " name " + materialParams.get(pI).getParamName());
+ }
+ mScene.appendRenderable(d);
+ //group.appendChildren(d);
+ }
+ }
+ }
+
+ private void updateLight(Element shape, Transform t) {
+ String lightURL = shape.getAttribute("url");
+ // collada uses a uri structure to link things,
+ // but we ignore it for now and do a simple search
+ LightBase light = mLights.get(lightURL.substring(1));
+ if (light != null) {
+ light.setTransform(t);
+ //Log.v(TAG, "Set Light " + light.getName() + " " + t.getName());
+ }
+ }
+
+ private void updateCamera(Element shape, Transform t) {
+ String camURL = shape.getAttribute("url");
+ // collada uses a uri structure to link things,
+ // but we ignore it for now and do a simple search
+ Camera cam = mCameras.get(camURL.substring(1));
+ if (cam != null) {
+ cam.setTransform(t);
+ //Log.v(TAG, "Set Camera " + cam.getName() + " " + t.getName());
+ }
+ }
+
+ private void getNode(Element node, Transform parent, String indent) {
+ String name = node.getAttribute("name");
+ String id = node.getAttribute("id");
+ CompoundTransform current = new CompoundTransform();
+ current.setName(name);
+ if (parent != null) {
+ parent.appendChild(current);
+ } else {
+ mScene.appendTransform(current);
+ }
+
+ mScene.addToTransformMap(current);
+
+ //Log.v(TAG, indent + "|");
+ //Log.v(TAG, indent + "[" + name + "]");
+
+ Node childNode = node.getFirstChild();
+ while (childNode != null) {
+ if (childNode.getNodeType() == Node.ELEMENT_NODE) {
+ Element field = (Element)childNode;
+ String fieldName = field.getTagName();
+ String description = field.getAttribute("sid");
+ if (fieldName.equals("translate")) {
+ Float3 value = getFloat3(field);
+ current.addComponent(new TranslateComponent(description, value));
+ //Log.v(TAG, indent + " translate " + description + toString(value));
+ } else if (fieldName.equals("rotate")) {
+ Float4 value = getFloat4(field);
+ //Log.v(TAG, indent + " rotate " + description + toString(value));
+ Float3 axis = new Float3(value.x, value.y, value.z);
+ current.addComponent(new RotateComponent(description, axis, value.w));
+ } else if (fieldName.equals("scale")) {
+ Float3 value = getFloat3(field);
+ //Log.v(TAG, indent + " scale " + description + toString(value));
+ current.addComponent(new ScaleComponent(description, value));
+ } else if (fieldName.equals("instance_geometry")) {
+ getRenderable(field, current);
+ } else if (fieldName.equals("instance_light")) {
+ updateLight(field, current);
+ } else if (fieldName.equals("instance_camera")) {
+ updateCamera(field, current);
+ } else if (fieldName.equals("node")) {
+ getNode(field, current, indent + " ");
+ }
+ }
+ childNode = childNode.getNextSibling();
+ }
+ }
+
+ // This will find the actual texture node, which is sometimes hidden behind a sampler
+ // and sometimes referenced directly
+ Texture2D getTexture(String samplerName) {
+ String texName = samplerName;
+
+ // Check to see if the image file is hidden by a sampler surface link combo
+ Element sampler = mDom.getElementById(samplerName);
+ if (sampler != null) {
+ NodeList nl = sampler.getElementsByTagName("source");
+ if (nl != null && nl.getLength() == 1) {
+ Element ref = (Element)nl.item(0);
+ String surfaceName = getString(ref);
+ if (surfaceName == null) {
+ return null;
+ }
+
+ Element surface = mDom.getElementById(surfaceName);
+ if (surface == null) {
+ return null;
+ }
+ nl = surface.getElementsByTagName("init_from");
+ if (nl != null && nl.getLength() == 1) {
+ ref = (Element)nl.item(0);
+ texName = getString(ref);
+ }
+ }
+ }
+
+ //Log.v(TAG, "Extracted texture name " + texName);
+ return mImages.get(texName);
+ }
+
+ void extractParams(Element fx, ArrayList<ShaderParam> params) {
+ Node paramNode = fx.getFirstChild();
+ while (paramNode != null) {
+ if (paramNode.getNodeType() == Node.ELEMENT_NODE) {
+ String name = paramNode.getNodeName();
+ // Now find what type it is
+ Node typeNode = paramNode.getFirstChild();
+ while (typeNode != null && typeNode.getNodeType() != Node.ELEMENT_NODE) {
+ typeNode = typeNode.getNextSibling();
+ }
+ String paramType = typeNode.getNodeName();
+ Element typeElem = (Element)typeNode;
+ ShaderParam sceneParam = null;
+ if (paramType.equals("color")) {
+ Float4Param f4p = new Float4Param(name);
+ Float4 value = getFloat4(typeElem);
+ f4p.setValue(value);
+ sceneParam = f4p;
+ //Log.v(TAG, "Extracted " + sceneParam.getParamName() + " value " + toString(value));
+ } else if (paramType.equals("float")) {
+ Float4Param f4p = new Float4Param(name);
+ float value = getFloat(typeElem);
+ f4p.setValue(new Float4(value, value, value, value));
+ sceneParam = f4p;
+ //Log.v(TAG, "Extracted " + sceneParam.getParamName() + " value " + value);
+ } else if (paramType.equals("texture")) {
+ String samplerName = typeElem.getAttribute("texture");
+ Texture2D tex = getTexture(samplerName);
+ TextureParam texP = new TextureParam(name);
+ texP.setTexture(tex);
+ sceneParam = texP;
+ //Log.v(TAG, "Extracted texture " + tex);
+ }
+ if (sceneParam != null) {
+ params.add(sceneParam);
+ }
+ }
+ paramNode = paramNode.getNextSibling();
+ }
+ }
+
+ private void convertMaterials(Element mat) {
+ String id = mat.getAttribute("id");
+ NodeList nl = mat.getElementsByTagName("instance_effect");
+ if (nl != null && nl.getLength() == 1) {
+ Element ref = (Element)nl.item(0);
+ String url = ref.getAttribute("url");
+ ArrayList<ShaderParam> params = mEffectsParams.get(url.substring(1));
+ mEffectsParams.put(id, params);
+ }
+ }
+
+ private void convertGeometries(Element geo) {
+ String id = geo.getAttribute("id");
+ String name = geo.getAttribute("name");
+ if (!id.equals(name)) {
+ mMeshIdNameMap.put(id, name);
+ }
+ }
+
+ private void convertEffects(Element fx) {
+ String id = fx.getAttribute("id");
+ ArrayList<ShaderParam> params = new ArrayList<ShaderParam>();
+
+ NodeList nl = fx.getElementsByTagName("newparam");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element field = (Element)nl.item(i);
+ field.setIdAttribute("sid", true);
+ }
+ }
+
+ nl = fx.getElementsByTagName("blinn");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element field = (Element)nl.item(i);
+ //Log.v(TAG, "blinn");
+ extractParams(field, params);
+ }
+ }
+ nl = fx.getElementsByTagName("lambert");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element field = (Element)nl.item(i);
+ //Log.v(TAG, "lambert");
+ extractParams(field, params);
+ }
+ }
+ nl = fx.getElementsByTagName("phong");
+ if (nl != null) {
+ for(int i = 0; i < nl.getLength(); i++) {
+ Element field = (Element)nl.item(i);
+ //Log.v(TAG, "phong");
+ extractParams(field, params);
+ }
+ }
+ mEffectsParams.put(id, params);
+ }
+
+ private void convertLight(Element light) {
+ String name = light.getAttribute("name");
+ String id = light.getAttribute("id");
+
+ // Determine type
+ String[] knownTypes = { "point", "spot", "directional" };
+ final int POINT_LIGHT = 0;
+ final int SPOT_LIGHT = 1;
+ final int DIR_LIGHT = 2;
+ int type = -1;
+ for (int i = 0; i < knownTypes.length; i ++) {
+ NodeList nl = light.getElementsByTagName(knownTypes[i]);
+ if (nl != null && nl.getLength() != 0) {
+ type = i;
+ break;
+ }
+ }
+
+ //Log.v(TAG, "Found Light Type " + type);
+
+ LightBase sceneLight = null;
+ switch (type) {
+ case POINT_LIGHT:
+ sceneLight = new PointLight();
+ break;
+ case SPOT_LIGHT: // TODO: finish light types
+ break;
+ case DIR_LIGHT: // TODO: finish light types
+ break;
+ }
+
+ if (sceneLight == null) {
+ return;
+ }
+
+ Float3 color = getFloat3(light, "color");
+ sceneLight.setColor(color.x, color.y, color.z);
+ sceneLight.setName(name);
+ mScene.appendLight(sceneLight);
+ mLights.put(id, sceneLight);
+
+ //Log.v(TAG, "Light " + name + " color " + toString(color));
+ }
+
+ private void convertCamera(Element camera) {
+ String name = camera.getAttribute("name");
+ String id = camera.getAttribute("id");
+ float fov = 30.0f;
+ if (getString(camera, "yfov") != null) {
+ fov = getFloat(camera, "yfov");
+ } else if(getString(camera, "xfov") != null) {
+ float aspect = getFloat(camera, "aspect_ratio");
+ fov = getFloat(camera, "xfov") / aspect;
+ }
+
+ float near = getFloat(camera, "znear");
+ float far = getFloat(camera, "zfar");
+
+ Camera sceneCamera = new Camera();
+ sceneCamera.setFOV(fov);
+ sceneCamera.setNear(near);
+ sceneCamera.setFar(far);
+ sceneCamera.setName(name);
+ mScene.appendCamera(sceneCamera);
+ mCameras.put(id, sceneCamera);
+ }
+
+ private void convertImage(Element img) {
+ String name = img.getAttribute("name");
+ String id = img.getAttribute("id");
+ String file = getString(img, "init_from");
+
+ Texture2D tex = new Texture2D();
+ tex.setFileName(file);
+ tex.setFileDir(mRootDir);
+ mScene.appendTextures(tex);
+ mImages.put(id, tex);
+ }
+
+ private void getScene(Element scene) {
+ String name = scene.getAttribute("name");
+ String id = scene.getAttribute("id");
+
+ Node childNode = scene.getFirstChild();
+ while (childNode != null) {
+ if (childNode.getNodeType() == Node.ELEMENT_NODE) {
+ String indent = "";
+ getNode((Element)childNode, null, indent);
+ }
+ childNode = childNode.getNextSibling();
+ }
+ }
+
+ private String getString(Element elem, String name) {
+ String text = null;
+ NodeList nl = elem.getElementsByTagName(name);
+ if (nl != null && nl.getLength() != 0) {
+ text = ((Element)nl.item(0)).getFirstChild().getNodeValue();
+ }
+ return text;
+ }
+
+ private String getString(Element elem) {
+ String text = null;
+ text = elem.getFirstChild().getNodeValue();
+ return text;
+ }
+
+ private int getInt(Element elem, String name) {
+ return Integer.parseInt(getString(elem, name));
+ }
+
+ private float getFloat(Element elem, String name) {
+ return Float.parseFloat(getString(elem, name));
+ }
+
+ private float getFloat(Element elem) {
+ return Float.parseFloat(getString(elem));
+ }
+
+ private Float3 parseFloat3(String valueString) {
+ StringTokenizer st = new StringTokenizer(valueString);
+ float x = Float.parseFloat(st.nextToken());
+ float y = Float.parseFloat(st.nextToken());
+ float z = Float.parseFloat(st.nextToken());
+ return new Float3(x, y, z);
+ }
+
+ private Float4 parseFloat4(String valueString) {
+ StringTokenizer st = new StringTokenizer(valueString);
+ float x = Float.parseFloat(st.nextToken());
+ float y = Float.parseFloat(st.nextToken());
+ float z = Float.parseFloat(st.nextToken());
+ float w = Float.parseFloat(st.nextToken());
+ return new Float4(x, y, z, w);
+ }
+
+ private Float3 getFloat3(Element elem, String name) {
+ String valueString = getString(elem, name);
+ return parseFloat3(valueString);
+ }
+
+ private Float4 getFloat4(Element elem, String name) {
+ String valueString = getString(elem, name);
+ return parseFloat4(valueString);
+ }
+
+ private Float3 getFloat3(Element elem) {
+ String valueString = getString(elem);
+ return parseFloat3(valueString);
+ }
+
+ private Float4 getFloat4(Element elem) {
+ String valueString = getString(elem);
+ return parseFloat4(valueString);
+ }
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ColladaScene.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ColladaScene.java
new file mode 100644
index 0000000..301075e
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ColladaScene.java
@@ -0,0 +1,139 @@
+/*
+ * 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.scenegraph;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.BufferedInputStream;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.AsyncTask;
+import android.renderscript.*;
+import android.renderscript.Allocation.MipmapControl;
+import android.renderscript.Element.Builder;
+import android.renderscript.Font.Style;
+import android.renderscript.Program.TextureType;
+import android.renderscript.ProgramStore.DepthFunc;
+import android.util.Log;
+import com.android.scenegraph.SceneManager.SceneLoadedCallback;
+
+
+public class ColladaScene {
+
+ private String modelName;
+ private static String TAG = "ColladaScene";
+ private final int STATE_LAST_FOCUS = 1;
+ boolean mLoadFromSD = false;
+
+ SceneLoadedCallback mCallback;
+
+ public ColladaScene(String name, SceneLoadedCallback cb) {
+ modelName = name;
+ mCallback = cb;
+ }
+
+ public void init(RenderScriptGL rs, Resources res) {
+ mRS = rs;
+ mRes = res;
+
+ mLoadFromSD = SceneManager.isSDCardPath(modelName);
+
+ new ColladaLoaderTask().execute(modelName);
+ }
+
+ private Resources mRes;
+ private RenderScriptGL mRS;
+ Scene mActiveScene;
+
+ private class ColladaLoaderTask extends AsyncTask<String, Void, Boolean> {
+ ColladaParser sceneSource;
+ protected Boolean doInBackground(String... names) {
+ String rootDir = names[0].substring(0, names[0].lastIndexOf('/') + 1);
+ long start = System.currentTimeMillis();
+ sceneSource = new ColladaParser();
+ InputStream is = null;
+ try {
+ if (!mLoadFromSD) {
+ is = mRes.getAssets().open(names[0]);
+ } else {
+ File f = new File(names[0]);
+ is = new BufferedInputStream(new FileInputStream(f));
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Could not open collada file");
+ return new Boolean(false);
+ }
+ long end = System.currentTimeMillis();
+ Log.v("TIMER", "Stream load time: " + (end - start));
+
+ start = System.currentTimeMillis();
+ sceneSource.init(is, rootDir);
+ end = System.currentTimeMillis();
+ Log.v("TIMER", "Collada parse time: " + (end - start));
+ return new Boolean(true);
+ }
+
+ protected void onPostExecute(Boolean result) {
+ mActiveScene = sceneSource.getScene();
+ if (mCallback != null) {
+ mCallback.mLoadedScene = mActiveScene;
+ mCallback.run();
+ }
+
+ String shortName = modelName.substring(0, modelName.lastIndexOf('.'));
+ new A3DLoaderTask().execute(shortName + ".a3d");
+ }
+ }
+
+ private class A3DLoaderTask extends AsyncTask<String, Void, Boolean> {
+ protected Boolean doInBackground(String... names) {
+ long start = System.currentTimeMillis();
+ FileA3D model;
+ if (!mLoadFromSD) {
+ model = FileA3D.createFromAsset(mRS, mRes.getAssets(), names[0]);
+ } else {
+ model = FileA3D.createFromFile(mRS, names[0]);
+ }
+ int numModels = model.getIndexEntryCount();
+ for (int i = 0; i < numModels; i ++) {
+ FileA3D.IndexEntry entry = model.getIndexEntry(i);
+ if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) {
+ mActiveScene.meshLoaded(entry.getMesh());
+ }
+ }
+ long end = System.currentTimeMillis();
+ Log.v("TIMER", "A3D load time: " + (end - start));
+ return new Boolean(true);
+ }
+
+ protected void onPostExecute(Boolean result) {
+ }
+ }
+
+}
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/CompoundTransform.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/CompoundTransform.java
new file mode 100644
index 0000000..d995dd0
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/CompoundTransform.java
@@ -0,0 +1,197 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+
+import com.android.scenegraph.SceneManager;
+
+import android.renderscript.*;
+import android.renderscript.Float3;
+import android.renderscript.Matrix4f;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class CompoundTransform extends Transform {
+
+ public static abstract class Component {
+ String mName;
+ CompoundTransform mParent;
+ int mParentIndex;
+ protected ScriptField_TransformComponent_s.Item mData;
+
+ Component(int type, String name) {
+ mData = new ScriptField_TransformComponent_s.Item();
+ mData.type = type;
+ mName = name;
+ }
+
+ void setNameAlloc() {
+ RenderScriptGL rs = SceneManager.getRS();
+ if (mData.name != null) {
+ return;
+ }
+ mData.name = SceneManager.getCachedAlloc(getName());
+ if (mData.name == null) {
+ mData.name = SceneManager.getStringAsAllocation(rs, getName());
+ SceneManager.cacheAlloc(getName(), mData.name);
+ }
+ }
+
+ ScriptField_TransformComponent_s.Item getRSData() {
+ setNameAlloc();
+ return mData;
+ }
+
+ protected void update() {
+ if (mParent != null) {
+ mParent.updateRSComponent(this);
+ }
+ }
+
+ public String getName() {
+ return mName;
+ }
+ }
+
+ public static class TranslateComponent extends Component {
+ public TranslateComponent(String name, Float3 translate) {
+ super(ScriptC_export.const_Transform_TRANSLATE, name);
+ setValue(translate);
+ }
+ public Float3 getValue() {
+ return new Float3(mData.value.x, mData.value.y, mData.value.z);
+ }
+ public void setValue(Float3 val) {
+ mData.value.x = val.x;
+ mData.value.y = val.y;
+ mData.value.z = val.z;
+ update();
+ }
+ }
+
+ public static class RotateComponent extends Component {
+ public RotateComponent(String name, Float3 axis, float angle) {
+ super(ScriptC_export.const_Transform_ROTATE, name);
+ setAxis(axis);
+ setAngle(angle);
+ }
+ public Float3 getAxis() {
+ return new Float3(mData.value.x, mData.value.y, mData.value.z);
+ }
+ public float getAngle() {
+ return mData.value.w;
+ }
+ public void setAxis(Float3 val) {
+ mData.value.x = val.x;
+ mData.value.y = val.y;
+ mData.value.z = val.z;
+ update();
+ }
+ public void setAngle(float val) {
+ mData.value.w = val;
+ update();
+ }
+ }
+
+ public static class ScaleComponent extends Component {
+ public ScaleComponent(String name, Float3 scale) {
+ super(ScriptC_export.const_Transform_SCALE, name);
+ setValue(scale);
+ }
+ public Float3 getValue() {
+ return new Float3(mData.value.x, mData.value.y, mData.value.z);
+ }
+ public void setValue(Float3 val) {
+ mData.value.x = val.x;
+ mData.value.y = val.y;
+ mData.value.z = val.z;
+ update();
+ }
+ }
+
+ ScriptField_TransformComponent_s mComponentField;
+ public ArrayList<Component> mTransformComponents;
+
+ public CompoundTransform() {
+ mTransformComponents = new ArrayList<Component>();
+ }
+
+ public void addComponent(Component c) {
+ if (c.mParent != null) {
+ throw new IllegalArgumentException("Transform components may not be shared");
+ }
+ c.mParent = this;
+ c.mParentIndex = mTransformComponents.size();
+ mTransformComponents.add(c);
+ updateRSComponentAllocation();
+ }
+
+ public void setComponent(int index, Component c) {
+ if (c.mParent != null) {
+ throw new IllegalArgumentException("Transform components may not be shared");
+ }
+ if (index >= mTransformComponents.size()) {
+ throw new IllegalArgumentException("Invalid component index");
+ }
+ c.mParent = this;
+ c.mParentIndex = index;
+ mTransformComponents.set(index, c);
+ updateRSComponent(c);
+ }
+
+ void updateRSComponent(Component c) {
+ if (mField == null || mComponentField == null) {
+ return;
+ }
+ mComponentField.set(c.getRSData(), c.mParentIndex, true);
+ mField.set_isDirty(0, 1, true);
+ }
+
+ void updateRSComponentAllocation() {
+ if (mField == null) {
+ return;
+ }
+ initLocalData();
+
+ mField.set_components(0, mTransformData.components, false);
+ mField.set_isDirty(0, 1, true);
+ }
+
+ void initLocalData() {
+ RenderScriptGL rs = SceneManager.getRS();
+ int numComponenets = mTransformComponents.size();
+ if (numComponenets > 0) {
+ mComponentField = new ScriptField_TransformComponent_s(rs, numComponenets);
+ for (int i = 0; i < numComponenets; i ++) {
+ Component ith = mTransformComponents.get(i);
+ mComponentField.set(ith.getRSData(), i, false);
+ }
+ mComponentField.copyAll();
+
+ mTransformData.components = mComponentField.getAllocation();
+ }
+ }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Float4Param.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Float4Param.java
new file mode 100644
index 0000000..1502458
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Float4Param.java
@@ -0,0 +1,146 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+
+import com.android.scenegraph.Scene;
+import com.android.scenegraph.SceneManager;
+
+import android.renderscript.Element;
+import android.renderscript.Float4;
+import android.renderscript.Matrix4f;
+import android.renderscript.ProgramFragment;
+import android.renderscript.ProgramStore;
+import android.renderscript.ProgramVertex;
+import android.renderscript.RenderScriptGL;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class Float4Param extends ShaderParam {
+ private static String TAG = "Float4Param";
+
+ LightBase mLight;
+
+ public Float4Param(String name) {
+ super(name);
+ }
+
+ public Float4Param(String name, float x) {
+ super(name);
+ set(x, 0, 0, 0);
+ }
+
+ public Float4Param(String name, float x, float y) {
+ super(name);
+ set(x, y, 0, 0);
+ }
+
+ public Float4Param(String name, float x, float y, float z) {
+ super(name);
+ set(x, y, z, 0);
+ }
+
+ public Float4Param(String name, float x, float y, float z, float w) {
+ super(name);
+ set(x, y, z, w);
+ }
+
+ void set(float x, float y, float z, float w) {
+ mData.float_value.x = x;
+ mData.float_value.y = y;
+ mData.float_value.z = z;
+ mData.float_value.w = w;
+ if (mField != null) {
+ mField.set_float_value(0, mData.float_value, true);
+ }
+ incTimestamp();
+ }
+
+ public void setValue(Float4 v) {
+ set(v.x, v.y, v.z, v.w);
+ }
+
+ public Float4 getValue() {
+ return mData.float_value;
+ }
+
+ public void setLight(LightBase l) {
+ mLight = l;
+ if (mField != null) {
+ mData.light = mLight.getRSData().getAllocation();
+ mField.set_light(0, mData.light, true);
+ }
+ incTimestamp();
+ }
+
+ boolean findLight(String property) {
+ String indexStr = mParamName.substring(property.length() + 1);
+ if (indexStr == null) {
+ Log.e(TAG, "Invalid light index.");
+ return false;
+ }
+ int index = Integer.parseInt(indexStr);
+ if (index == -1) {
+ return false;
+ }
+ Scene parentScene = SceneManager.getInstance().getActiveScene();
+ ArrayList<LightBase> allLights = parentScene.getLights();
+ if (index >= allLights.size()) {
+ return false;
+ }
+ mLight = allLights.get(index);
+ if (mLight == null) {
+ return false;
+ }
+ return true;
+ }
+
+ int getTypeFromName() {
+ int paramType = ScriptC_export.const_ShaderParam_FLOAT4_DATA;
+ if (mParamName.equalsIgnoreCase(cameraPos)) {
+ paramType = ScriptC_export.const_ShaderParam_FLOAT4_CAMERA_POS;
+ } else if(mParamName.equalsIgnoreCase(cameraDir)) {
+ paramType = ScriptC_export.const_ShaderParam_FLOAT4_CAMERA_DIR;
+ } else if(mParamName.startsWith(lightColor) && findLight(lightColor)) {
+ paramType = ScriptC_export.const_ShaderParam_FLOAT4_LIGHT_COLOR;
+ } else if(mParamName.startsWith(lightPos) && findLight(lightPos)) {
+ paramType = ScriptC_export.const_ShaderParam_FLOAT4_LIGHT_POS;
+ } else if(mParamName.startsWith(lightDir) && findLight(lightDir)) {
+ paramType = ScriptC_export.const_ShaderParam_FLOAT4_LIGHT_DIR;
+ }
+ return paramType;
+ }
+
+ void initLocalData() {
+ mData.type = getTypeFromName();
+ if (mCamera != null) {
+ mData.camera = mCamera.getRSData().getAllocation();
+ }
+ if (mLight != null) {
+ mData.light = mLight.getRSData().getAllocation();
+ }
+ }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/FragmentShader.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/FragmentShader.java
new file mode 100644
index 0000000..c8cc3ac
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/FragmentShader.java
@@ -0,0 +1,167 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+
+import com.android.scenegraph.TextureBase;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.renderscript.ProgramFragment.Builder;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class FragmentShader extends Shader {
+ ProgramFragment mProgram;
+ ScriptField_FragmentShader_s mField;
+
+ public static class Builder {
+
+ FragmentShader mShader;
+ ProgramFragment.Builder mBuilder;
+
+ public Builder(RenderScriptGL rs) {
+ mShader = new FragmentShader();
+ mBuilder = new ProgramFragment.Builder(rs);
+ }
+
+ public Builder setShader(Resources resources, int resourceID) {
+ mBuilder.setShader(resources, resourceID);
+ return this;
+ }
+
+ public Builder setObjectConst(Type type) {
+ mShader.mPerObjConstants = type;
+ return this;
+ }
+
+ public Builder setShaderConst(Type type) {
+ mShader.mPerShaderConstants = type;
+ return this;
+ }
+
+ public Builder addShaderTexture(Program.TextureType texType, String name) {
+ mShader.mShaderTextureNames.add(name);
+ mShader.mShaderTextureTypes.add(texType);
+ return this;
+ }
+
+ public Builder addTexture(Program.TextureType texType, String name) {
+ mShader.mTextureNames.add(name);
+ mShader.mTextureTypes.add(texType);
+ return this;
+ }
+
+ public FragmentShader create() {
+ if (mShader.mPerShaderConstants != null) {
+ mBuilder.addConstant(mShader.mPerShaderConstants);
+ }
+ if (mShader.mPerObjConstants != null) {
+ mBuilder.addConstant(mShader.mPerObjConstants);
+ }
+ for (int i = 0; i < mShader.mTextureTypes.size(); i ++) {
+ mBuilder.addTexture(mShader.mTextureTypes.get(i));
+ }
+ for (int i = 0; i < mShader.mShaderTextureTypes.size(); i ++) {
+ mBuilder.addTexture(mShader.mShaderTextureTypes.get(i));
+ }
+
+ mShader.mProgram = mBuilder.create();
+ return mShader;
+ }
+ }
+
+ public ProgramFragment getProgram() {
+ return mProgram;
+ }
+
+ ScriptField_ShaderParam_s getTextureParams() {
+ RenderScriptGL rs = SceneManager.getRS();
+ Resources res = SceneManager.getRes();
+ if (rs == null || res == null) {
+ return null;
+ }
+
+ ArrayList<ScriptField_ShaderParam_s.Item> paramList;
+ paramList = new ArrayList<ScriptField_ShaderParam_s.Item>();
+
+ int shaderTextureStart = mTextureTypes.size();
+ for (int i = 0; i < mShaderTextureNames.size(); i ++) {
+ ShaderParam sp = mSourceParams.get(mShaderTextureNames.get(i));
+ if (sp != null && sp instanceof TextureParam) {
+ TextureParam p = (TextureParam)sp;
+ ScriptField_ShaderParam_s.Item paramRS = new ScriptField_ShaderParam_s.Item();
+ paramRS.bufferOffset = shaderTextureStart + i;
+ paramRS.transformTimestamp = 0;
+ paramRS.dataTimestamp = 0;
+ paramRS.data = p.getRSData().getAllocation();
+ paramList.add(paramRS);
+ }
+ }
+
+ ScriptField_ShaderParam_s rsParams = null;
+ int paramCount = paramList.size();
+ if (paramCount != 0) {
+ rsParams = new ScriptField_ShaderParam_s(rs, paramCount);
+ for (int i = 0; i < paramCount; i++) {
+ rsParams.set(paramList.get(i), i, false);
+ }
+ rsParams.copyAll();
+ }
+ return rsParams;
+ }
+
+ ScriptField_FragmentShader_s getRSData() {
+ if (mField != null) {
+ return mField;
+ }
+
+ RenderScriptGL rs = SceneManager.getRS();
+ Resources res = SceneManager.getRes();
+ if (rs == null || res == null) {
+ return null;
+ }
+
+ ScriptField_FragmentShader_s.Item item = new ScriptField_FragmentShader_s.Item();
+ item.program = mProgram;
+
+ ScriptField_ShaderParam_s texParams = getTextureParams();
+ if (texParams != null) {
+ item.shaderTextureParams = texParams.getAllocation();
+ }
+
+ linkConstants(rs);
+ if (mPerShaderConstants != null) {
+ item.shaderConst = mConstantBuffer;
+ item.shaderConstParams = mConstantBufferParams.getAllocation();
+ mProgram.bindConstants(item.shaderConst, 0);
+ }
+
+ item.objectConstIndex = -1;
+ if (mPerObjConstants != null) {
+ item.objectConstIndex = mPerShaderConstants != null ? 1 : 0;
+ }
+
+ mField = new ScriptField_FragmentShader_s(rs, 1);
+ mField.set(item, 0, true);
+ return mField;
+ }
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/LightBase.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/LightBase.java
new file mode 100644
index 0000000..8f5e2e7
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/LightBase.java
@@ -0,0 +1,111 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+
+import android.renderscript.Float3;
+import android.renderscript.Float4;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScriptGL;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public abstract class LightBase extends SceneGraphBase {
+ static final int RS_LIGHT_POINT = 0;
+ static final int RS_LIGHT_DIRECTIONAL = 1;
+
+ ScriptField_Light_s mField;
+ ScriptField_Light_s.Item mFieldData;
+ Transform mTransform;
+ Float4 mColor;
+ float mIntensity;
+ public LightBase() {
+ mColor = new Float4(0.0f, 0.0f, 0.0f, 0.0f);
+ mIntensity = 1.0f;
+ }
+
+ public void setTransform(Transform t) {
+ mTransform = t;
+ updateRSData();
+ }
+
+ public void setColor(float r, float g, float b) {
+ mColor.x = r;
+ mColor.y = g;
+ mColor.z = b;
+ updateRSData();
+ }
+
+ public void setColor(Float3 c) {
+ setColor(c.x, c.y, c.z);
+ }
+
+ public void setIntensity(float i) {
+ mIntensity = i;
+ updateRSData();
+ }
+
+ public void setName(String n) {
+ super.setName(n);
+ updateRSData();
+ }
+
+ protected void updateRSData() {
+ if (mField == null) {
+ return;
+ }
+ RenderScriptGL rs = SceneManager.getRS();
+ mFieldData.transformMatrix = mTransform.getRSData().getAllocation();
+ mFieldData.name = getNameAlloc(rs);
+ mFieldData.color = mColor;
+ mFieldData.intensity = mIntensity;
+
+ initLocalData();
+
+ mField.set(mFieldData, 0, true);
+ }
+
+ abstract void initLocalData();
+
+ ScriptField_Light_s getRSData() {
+ if (mField != null) {
+ return mField;
+ }
+
+ RenderScriptGL rs = SceneManager.getRS();
+ if (rs == null) {
+ return null;
+ }
+ if (mField == null) {
+ mField = new ScriptField_Light_s(rs, 1);
+ mFieldData = new ScriptField_Light_s.Item();
+ }
+
+ updateRSData();
+
+ return mField;
+ }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/MatrixTransform.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/MatrixTransform.java
new file mode 100644
index 0000000..6d70bc9
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/MatrixTransform.java
@@ -0,0 +1,60 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+
+import android.renderscript.Matrix4f;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class MatrixTransform extends Transform {
+
+ Matrix4f mLocalMatrix;
+ public MatrixTransform() {
+ mLocalMatrix = new Matrix4f();
+ }
+
+ public void setMatrix(Matrix4f matrix) {
+ mLocalMatrix = matrix;
+ updateRSData();
+ }
+
+ public Matrix4f getMatrix() {
+ return new Matrix4f(mLocalMatrix.getArray());
+ }
+
+ void initLocalData() {
+ mTransformData.localMat = mLocalMatrix;
+ }
+
+ void updateRSData() {
+ if (mField == null) {
+ return;
+ }
+ mField.set_localMat(0, mLocalMatrix, false);
+ mField.set_isDirty(0, 1, true);
+ }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/PointLight.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/PointLight.java
new file mode 100644
index 0000000..574bafc
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/PointLight.java
@@ -0,0 +1,43 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+
+import android.renderscript.Matrix4f;
+import android.renderscript.ProgramFragment;
+import android.renderscript.ProgramStore;
+import android.renderscript.ProgramVertex;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class PointLight extends LightBase {
+ public PointLight() {
+ }
+
+ void initLocalData() {
+ mFieldData.type = RS_LIGHT_POINT;
+ }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderPass.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderPass.java
new file mode 100644
index 0000000..02fd69d
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderPass.java
@@ -0,0 +1,124 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+
+import android.util.Log;
+
+import android.renderscript.*;
+import android.content.res.Resources;
+
+/**
+ * @hide
+ */
+public class RenderPass extends SceneGraphBase {
+
+ TextureRenderTarget mColorTarget;
+ Float4 mClearColor;
+ boolean mShouldClearColor;
+
+ TextureRenderTarget mDepthTarget;
+ float mClearDepth;
+ boolean mShouldClearDepth;
+
+ ArrayList<RenderableBase> mObjectsToDraw;
+
+ Camera mCamera;
+
+ ScriptField_RenderPass_s.Item mRsField;
+
+ public RenderPass() {
+ mObjectsToDraw = new ArrayList<RenderableBase>();
+ mClearColor = new Float4(0.0f, 0.0f, 0.0f, 0.0f);
+ mShouldClearColor = true;
+ mClearDepth = 1.0f;
+ mShouldClearDepth = true;
+ }
+
+ public void appendRenderable(Renderable d) {
+ mObjectsToDraw.add(d);
+ }
+
+ public void setCamera(Camera c) {
+ mCamera = c;
+ }
+
+ public void setColorTarget(TextureRenderTarget colorTarget) {
+ mColorTarget = colorTarget;
+ }
+ public void setClearColor(Float4 clearColor) {
+ mClearColor = clearColor;
+ }
+ public void setShouldClearColor(boolean shouldClearColor) {
+ mShouldClearColor = shouldClearColor;
+ }
+
+ public void setDepthTarget(TextureRenderTarget depthTarget) {
+ mDepthTarget = depthTarget;
+ }
+ public void setClearDepth(float clearDepth) {
+ mClearDepth = clearDepth;
+ }
+ public void setShouldClearDepth(boolean shouldClearDepth) {
+ mShouldClearDepth = shouldClearDepth;
+ }
+
+ public ArrayList<RenderableBase> getRenderables() {
+ return mObjectsToDraw;
+ }
+
+ ScriptField_RenderPass_s.Item getRsField(RenderScriptGL rs, Resources res) {
+ if (mRsField != null) {
+ return mRsField;
+ }
+
+ mRsField = new ScriptField_RenderPass_s.Item();
+ if (mColorTarget != null) {
+ mRsField.color_target = mColorTarget.getRsData(true).get_texture(0);
+ }
+ if (mColorTarget != null) {
+ mRsField.depth_target = mDepthTarget.getRsData(true).get_texture(0);
+ }
+ mRsField.camera = mCamera != null ? mCamera.getRSData().getAllocation() : null;
+
+ if (mObjectsToDraw.size() != 0) {
+ Allocation drawableData = Allocation.createSized(rs,
+ Element.ALLOCATION(rs),
+ mObjectsToDraw.size());
+ Allocation[] drawableAllocs = new Allocation[mObjectsToDraw.size()];
+ for (int i = 0; i < mObjectsToDraw.size(); i ++) {
+ Renderable dI = (Renderable)mObjectsToDraw.get(i);
+ drawableAllocs[i] = dI.getRsField(rs, res).getAllocation();
+ }
+ drawableData.copyFrom(drawableAllocs);
+ mRsField.objects = drawableData;
+ }
+
+ mRsField.clear_color = mClearColor;
+ mRsField.clear_depth = mClearDepth;
+ mRsField.should_clear_color = mShouldClearColor;
+ mRsField.should_clear_depth = mShouldClearDepth;
+ return mRsField;
+ }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderState.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderState.java
new file mode 100644
index 0000000..c08a722
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderState.java
@@ -0,0 +1,111 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+import android.content.res.Resources;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.ProgramFragment;
+import android.renderscript.ProgramRaster;
+import android.renderscript.ProgramStore;
+import android.renderscript.ProgramVertex;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.RenderScript;
+import android.renderscript.RenderScriptGL;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class RenderState extends SceneGraphBase {
+ VertexShader mVertex;
+ FragmentShader mFragment;
+ ProgramStore mStore;
+ ProgramRaster mRaster;
+
+ ScriptField_RenderState_s mField;
+
+ public RenderState(VertexShader pv,
+ FragmentShader pf,
+ ProgramStore ps,
+ ProgramRaster pr) {
+ mVertex = pv;
+ mFragment = pf;
+ mStore = ps;
+ mRaster = pr;
+ }
+
+ public RenderState(RenderState r) {
+ mVertex = r.mVertex;
+ mFragment = r.mFragment;
+ mStore = r.mStore;
+ mRaster = r.mRaster;
+ }
+
+ public void setProgramVertex(VertexShader pv) {
+ mVertex = pv;
+ updateRSData();
+ }
+
+ public void setProgramFragment(FragmentShader pf) {
+ mFragment = pf;
+ updateRSData();
+ }
+
+ public void setProgramStore(ProgramStore ps) {
+ mStore = ps;
+ updateRSData();
+ }
+
+ public void setProgramRaster(ProgramRaster pr) {
+ mRaster = pr;
+ updateRSData();
+ }
+
+ void updateRSData() {
+ if (mField == null) {
+ return;
+ }
+ ScriptField_RenderState_s.Item item = new ScriptField_RenderState_s.Item();
+ item.pv = mVertex.getRSData().getAllocation();
+ item.pf = mFragment.getRSData().getAllocation();
+ item.ps = mStore;
+ item.pr = mRaster;
+
+ mField.set(item, 0, true);
+ }
+
+ public ScriptField_RenderState_s getRSData() {
+ if (mField != null) {
+ return mField;
+ }
+
+ RenderScriptGL rs = SceneManager.getRS();
+ if (rs == null) {
+ return null;
+ }
+
+ mField = new ScriptField_RenderState_s(rs, 1);
+ updateRSData();
+
+ return mField;
+ }
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Renderable.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Renderable.java
new file mode 100644
index 0000000..9f7ab41
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Renderable.java
@@ -0,0 +1,214 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import com.android.scenegraph.Float4Param;
+import com.android.scenegraph.SceneManager;
+import com.android.scenegraph.ShaderParam;
+import com.android.scenegraph.TransformParam;
+
+import android.content.res.Resources;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Element.DataType;
+import android.renderscript.Matrix4f;
+import android.renderscript.Mesh;
+import android.renderscript.ProgramFragment;
+import android.renderscript.ProgramStore;
+import android.renderscript.ProgramVertex;
+import android.renderscript.RenderScriptGL;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class Renderable extends RenderableBase {
+ HashMap<String, ShaderParam> mSourceParams;
+
+ RenderState mRenderState;
+ Transform mTransform;
+
+ String mMeshName;
+ String mMeshIndexName;
+
+ public String mMaterialName;
+
+ ScriptField_Renderable_s mField;
+ ScriptField_Renderable_s.Item mData;
+
+ public Renderable() {
+ mSourceParams = new HashMap<String, ShaderParam>();
+ mData = new ScriptField_Renderable_s.Item();
+ }
+
+ public void setCullType(int cull) {
+ mData.cullType = cull;
+ }
+
+ public void setRenderState(RenderState renderState) {
+ mRenderState = renderState;
+ if (mField != null) {
+ RenderScriptGL rs = SceneManager.getRS();
+ updateFieldItem(rs);
+ mField.set(mData, 0, true);
+ }
+ }
+
+ public void setMesh(Mesh mesh) {
+ mData.mesh = mesh;
+ if (mField != null) {
+ mField.set_mesh(0, mData.mesh, true);
+ }
+ }
+
+ public void setMesh(String mesh, String indexName) {
+ mMeshName = mesh;
+ mMeshIndexName = indexName;
+ }
+
+ public void setMaterialName(String name) {
+ mMaterialName = name;
+ }
+
+ public void setTransform(Transform t) {
+ mTransform = t;
+ if (mField != null) {
+ RenderScriptGL rs = SceneManager.getRS();
+ updateFieldItem(rs);
+ mField.set(mData, 0, true);
+ }
+ }
+
+ public void appendSourceParams(ShaderParam p) {
+ mSourceParams.put(p.getParamName(), p);
+ // Possibly lift this restriction later
+ if (mField != null) {
+ throw new RuntimeException("Can't add source params to objects that are rendering");
+ }
+ }
+
+ public void resolveMeshData(Mesh mesh) {
+ mData.mesh = mesh;
+ if (mData.mesh == null) {
+ Log.v("DRAWABLE: ", "*** NO MESH *** " + mMeshName);
+ return;
+ }
+ int subIndexCount = mData.mesh.getPrimitiveCount();
+ if (subIndexCount == 1 || mMeshIndexName == null) {
+ mData.meshIndex = 0;
+ } else {
+ for (int i = 0; i < subIndexCount; i ++) {
+ if (mData.mesh.getIndexSetAllocation(i).getName().equals(mMeshIndexName)) {
+ mData.meshIndex = i;
+ break;
+ }
+ }
+ }
+ if (mField != null) {
+ mField.set(mData, 0, true);
+ }
+ }
+
+ void updateTextures(RenderScriptGL rs) {
+ Iterator<ShaderParam> allParamsIter = mSourceParams.values().iterator();
+ int paramIndex = 0;
+ while (allParamsIter.hasNext()) {
+ ShaderParam sp = allParamsIter.next();
+ if (sp instanceof TextureParam) {
+ TextureParam p = (TextureParam)sp;
+ TextureBase tex = p.getTexture();
+ if (tex != null) {
+ mData.pf_textures[paramIndex++] = tex.getRsData(false).getAllocation();
+ }
+ }
+ }
+ ProgramFragment pf = mRenderState.mFragment.mProgram;
+ mData.pf_num_textures = pf != null ? Math.min(pf.getTextureCount(), paramIndex) : 0;
+ if (mField != null) {
+ mField.set_pf_textures(0, mData.pf_textures, true);
+ mField.set_pf_num_textures(0, mData.pf_num_textures, true);
+ }
+ }
+
+ public void setVisible(boolean vis) {
+ mData.cullType = vis ? 0 : 2;
+ if (mField != null) {
+ mField.set_cullType(0, mData.cullType, true);
+ }
+ }
+
+ ScriptField_Renderable_s getRsField(RenderScriptGL rs, Resources res) {
+ if (mField != null) {
+ return mField;
+ }
+ updateFieldItem(rs);
+ updateTextures(rs);
+
+ mField = new ScriptField_Renderable_s(rs, 1);
+ mField.set(mData, 0, true);
+
+ return mField;
+ }
+
+ void updateVertexConstants(RenderScriptGL rs) {
+ Allocation pvParams = null, vertexConstants = null;
+ VertexShader pv = mRenderState.mVertex;
+ if (pv != null && pv.getObjectConstants() != null) {
+ vertexConstants = Allocation.createTyped(rs, pv.getObjectConstants());
+ Element vertexConst = vertexConstants.getType().getElement();
+ pvParams = ShaderParam.fillInParams(vertexConst, mSourceParams,
+ mTransform).getAllocation();
+ }
+ mData.pv_const = vertexConstants;
+ mData.pv_constParams = pvParams;
+ }
+
+ void updateFragmentConstants(RenderScriptGL rs) {
+ Allocation pfParams = null, fragmentConstants = null;
+ FragmentShader pf = mRenderState.mFragment;
+ if (pf != null && pf.getObjectConstants() != null) {
+ fragmentConstants = Allocation.createTyped(rs, pf.getObjectConstants());
+ Element fragmentConst = fragmentConstants.getType().getElement();
+ pfParams = ShaderParam.fillInParams(fragmentConst, mSourceParams,
+ mTransform).getAllocation();
+ }
+ mData.pf_const = fragmentConstants;
+ mData.pf_constParams = pfParams;
+ }
+
+ void updateFieldItem(RenderScriptGL rs) {
+ updateVertexConstants(rs);
+ updateFragmentConstants(rs);
+
+ if (mTransform != null) {
+ mData.transformMatrix = mTransform.getRSData().getAllocation();
+ }
+ mData.name = getNameAlloc(rs);
+ mData.render_state = mRenderState.getRSData().getAllocation();
+ mData.bVolInitialized = 0;
+ }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderableBase.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderableBase.java
new file mode 100644
index 0000000..74535dd
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderableBase.java
@@ -0,0 +1,39 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+
+import android.renderscript.Matrix4f;
+import android.renderscript.ProgramFragment;
+import android.renderscript.ProgramStore;
+import android.renderscript.ProgramVertex;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class RenderableBase extends SceneGraphBase {
+ public RenderableBase() {
+ }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderableGroup.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderableGroup.java
new file mode 100644
index 0000000..590bbab
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/RenderableGroup.java
@@ -0,0 +1,47 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+
+import android.renderscript.Matrix4f;
+import android.renderscript.ProgramFragment;
+import android.renderscript.ProgramStore;
+import android.renderscript.ProgramVertex;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class RenderableGroup extends RenderableBase {
+
+ ArrayList<RenderableBase> mChildren;
+
+ public RenderableGroup() {
+ mChildren = new ArrayList<RenderableBase>();
+ }
+
+ public void appendChildren(RenderableBase d) {
+ mChildren.add(d);
+ }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Scene.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Scene.java
new file mode 100644
index 0000000..8c09860
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Scene.java
@@ -0,0 +1,308 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.android.scenegraph.SceneManager;
+import com.android.scenegraph.TextureBase;
+
+import android.content.res.Resources;
+import android.os.AsyncTask;
+import android.renderscript.*;
+import android.renderscript.Mesh;
+import android.renderscript.RenderScriptGL;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class Scene extends SceneGraphBase {
+ private static String TIMER_TAG = "TIMER";
+
+ CompoundTransform mRootTransforms;
+ HashMap<String, Transform> mTransformMap;
+ ArrayList<RenderPass> mRenderPasses;
+ ArrayList<LightBase> mLights;
+ ArrayList<Camera> mCameras;
+ ArrayList<FragmentShader> mFragmentShaders;
+ ArrayList<VertexShader> mVertexShaders;
+ ArrayList<RenderableBase> mRenderables;
+ HashMap<String, RenderableBase> mRenderableMap;
+ ArrayList<Texture2D> mTextures;
+
+ HashMap<String, ArrayList<Renderable> > mRenderableMeshMap;
+
+ // RS Specific stuff
+ ScriptField_SgTransform mTransformRSData;
+
+ RenderScriptGL mRS;
+ Resources mRes;
+
+ ScriptField_RenderPass_s mRenderPassAlloc;
+
+ public Scene() {
+ mRenderPasses = new ArrayList<RenderPass>();
+ mLights = new ArrayList<LightBase>();
+ mCameras = new ArrayList<Camera>();
+ mFragmentShaders = new ArrayList<FragmentShader>();
+ mVertexShaders = new ArrayList<VertexShader>();
+ mRenderables = new ArrayList<RenderableBase>();
+ mRenderableMap = new HashMap<String, RenderableBase>();
+ mRenderableMeshMap = new HashMap<String, ArrayList<Renderable> >();
+ mTextures = new ArrayList<Texture2D>();
+ mRootTransforms = new CompoundTransform();
+ mRootTransforms.setName("_scene_root_");
+ mTransformMap = new HashMap<String, Transform>();
+ }
+
+ public void appendTransform(Transform t) {
+ mRootTransforms.appendChild(t);
+ }
+
+ // temporary
+ public void addToTransformMap(Transform t) {
+ mTransformMap.put(t.getName(), t);
+ }
+
+ public Transform getTransformByName(String name) {
+ return mTransformMap.get(name);
+ }
+
+ public void appendRenderPass(RenderPass p) {
+ mRenderPasses.add(p);
+ }
+
+ public void clearRenderPasses() {
+ mRenderPasses.clear();
+ }
+
+ public void appendLight(LightBase l) {
+ mLights.add(l);
+ }
+
+ public void appendCamera(Camera c) {
+ mCameras.add(c);
+ }
+
+ public void appendShader(FragmentShader f) {
+ mFragmentShaders.add(f);
+ }
+
+ public void appendShader(VertexShader v) {
+ mVertexShaders.add(v);
+ }
+
+ public ArrayList<Camera> getCameras() {
+ return mCameras;
+ }
+
+ public ArrayList<LightBase> getLights() {
+ return mLights;
+ }
+
+ public void appendRenderable(RenderableBase d) {
+ mRenderables.add(d);
+ mRenderableMap.put(d.getName(), d);
+ }
+
+ public ArrayList<RenderableBase> getRenderables() {
+ return mRenderables;
+ }
+
+ public RenderableBase getRenderableByName(String name) {
+ return mRenderableMap.get(name);
+ }
+
+ public void appendTextures(Texture2D tex) {
+ mTextures.add(tex);
+ }
+
+ public void assignRenderStateToMaterial(RenderState renderState, String regex) {
+ Pattern pattern = Pattern.compile(regex);
+ int numRenderables = mRenderables.size();
+ for (int i = 0; i < numRenderables; i ++) {
+ Renderable shape = (Renderable)mRenderables.get(i);
+ Matcher m = pattern.matcher(shape.mMaterialName);
+ if (m.find()) {
+ shape.setRenderState(renderState);
+ }
+ }
+ }
+
+ public void assignRenderState(RenderState renderState) {
+ int numRenderables = mRenderables.size();
+ for (int i = 0; i < numRenderables; i ++) {
+ Renderable shape = (Renderable)mRenderables.get(i);
+ shape.setRenderState(renderState);
+ }
+ }
+
+ public void meshLoaded(Mesh m) {
+ ArrayList<Renderable> entries = mRenderableMeshMap.get(m.getName());
+ int numEntries = entries.size();
+ for (int i = 0; i < numEntries; i++) {
+ Renderable d = entries.get(i);
+ d.resolveMeshData(m);
+ }
+ }
+
+ void addToMeshMap(Renderable d) {
+ ArrayList<Renderable> entries = mRenderableMeshMap.get(d.mMeshName);
+ if (entries == null) {
+ entries = new ArrayList<Renderable>();
+ mRenderableMeshMap.put(d.mMeshName, entries);
+ }
+ entries.add(d);
+ }
+
+ public void destroyRS() {
+ SceneManager sceneManager = SceneManager.getInstance();
+ mTransformRSData = null;
+ sceneManager.mRenderLoop.bind_gRootNode(mTransformRSData);
+ sceneManager.mRenderLoop.set_gRenderableObjects(null);
+ mRenderPassAlloc = null;
+ sceneManager.mRenderLoop.set_gRenderPasses(null);
+ sceneManager.mRenderLoop.bind_gFrontToBack(null);
+ sceneManager.mRenderLoop.bind_gBackToFront(null);
+ sceneManager.mRenderLoop.set_gCameras(null);
+
+ mTransformMap = null;
+ mRenderPasses = null;
+ mLights = null;
+ mCameras = null;
+ mRenderables = null;
+ mRenderableMap = null;
+ mTextures = null;
+ mRenderableMeshMap = null;
+ mRootTransforms = null;
+ }
+
+ public void initRenderPassRS(RenderScriptGL rs, SceneManager sceneManager) {
+ if (mRenderPasses.size() != 0) {
+ mRenderPassAlloc = new ScriptField_RenderPass_s(mRS, mRenderPasses.size());
+ for (int i = 0; i < mRenderPasses.size(); i ++) {
+ mRenderPassAlloc.set(mRenderPasses.get(i).getRsField(mRS, mRes), i, false);
+ }
+ mRenderPassAlloc.copyAll();
+ sceneManager.mRenderLoop.set_gRenderPasses(mRenderPassAlloc.getAllocation());
+ }
+ }
+
+ private void addDrawables(RenderScriptGL rs, Resources res, SceneManager sceneManager) {
+ Allocation drawableData = Allocation.createSized(rs,
+ Element.ALLOCATION(rs),
+ mRenderables.size());
+ Allocation[] drawableAllocs = new Allocation[mRenderables.size()];
+ for (int i = 0; i < mRenderables.size(); i ++) {
+ Renderable dI = (Renderable)mRenderables.get(i);
+ addToMeshMap(dI);
+ drawableAllocs[i] = dI.getRsField(rs, res).getAllocation();
+ }
+ drawableData.copyFrom(drawableAllocs);
+ sceneManager.mRenderLoop.set_gRenderableObjects(drawableData);
+
+ initRenderPassRS(rs, sceneManager);
+ }
+
+ private void addShaders(RenderScriptGL rs, Resources res, SceneManager sceneManager) {
+ Allocation shaderData = Allocation.createSized(rs, Element.ALLOCATION(rs),
+ mVertexShaders.size());
+ Allocation[] shaderAllocs = new Allocation[mVertexShaders.size()];
+ for (int i = 0; i < mVertexShaders.size(); i ++) {
+ VertexShader sI = mVertexShaders.get(i);
+ shaderAllocs[i] = sI.getRSData().getAllocation();
+ }
+ shaderData.copyFrom(shaderAllocs);
+ sceneManager.mRenderLoop.set_gVertexShaders(shaderData);
+
+ shaderData = Allocation.createSized(rs, Element.ALLOCATION(rs), mFragmentShaders.size());
+ shaderAllocs = new Allocation[mFragmentShaders.size()];
+ for (int i = 0; i < mFragmentShaders.size(); i ++) {
+ FragmentShader sI = mFragmentShaders.get(i);
+ shaderAllocs[i] = sI.getRSData().getAllocation();
+ }
+ shaderData.copyFrom(shaderAllocs);
+ sceneManager.mRenderLoop.set_gFragmentShaders(shaderData);
+ }
+
+ public void initRS() {
+ SceneManager sceneManager = SceneManager.getInstance();
+ mRS = SceneManager.getRS();
+ mRes = SceneManager.getRes();
+ long start = System.currentTimeMillis();
+ mTransformRSData = mRootTransforms.getRSData();
+ long end = System.currentTimeMillis();
+ Log.v(TIMER_TAG, "Transform init time: " + (end - start));
+
+ start = System.currentTimeMillis();
+
+ sceneManager.mRenderLoop.bind_gRootNode(mTransformRSData);
+ end = System.currentTimeMillis();
+ Log.v(TIMER_TAG, "Script init time: " + (end - start));
+
+ start = System.currentTimeMillis();
+ addDrawables(mRS, mRes, sceneManager);
+ end = System.currentTimeMillis();
+ Log.v(TIMER_TAG, "Renderable init time: " + (end - start));
+
+ addShaders(mRS, mRes, sceneManager);
+
+ Allocation opaqueBuffer = null;
+ if (mRenderables.size() > 0) {
+ opaqueBuffer = Allocation.createSized(mRS, Element.U32(mRS), mRenderables.size());
+ }
+ Allocation transparentBuffer = null;
+ if (mRenderables.size() > 0) {
+ transparentBuffer = Allocation.createSized(mRS, Element.U32(mRS), mRenderables.size());
+ }
+
+ sceneManager.mRenderLoop.bind_gFrontToBack(opaqueBuffer);
+ sceneManager.mRenderLoop.bind_gBackToFront(transparentBuffer);
+
+ if (mCameras.size() > 0) {
+ Allocation cameraData;
+ cameraData = Allocation.createSized(mRS, Element.ALLOCATION(mRS), mCameras.size());
+ Allocation[] cameraAllocs = new Allocation[mCameras.size()];
+ for (int i = 0; i < mCameras.size(); i ++) {
+ cameraAllocs[i] = mCameras.get(i).getRSData().getAllocation();
+ }
+ cameraData.copyFrom(cameraAllocs);
+ sceneManager.mRenderLoop.set_gCameras(cameraData);
+ }
+
+ if (mLights.size() > 0) {
+ Allocation lightData = Allocation.createSized(mRS,
+ Element.ALLOCATION(mRS),
+ mLights.size());
+ Allocation[] lightAllocs = new Allocation[mLights.size()];
+ for (int i = 0; i < mLights.size(); i ++) {
+ lightAllocs[i] = mLights.get(i).getRSData().getAllocation();
+ }
+ lightData.copyFrom(lightAllocs);
+ sceneManager.mRenderLoop.set_gLights(lightData);
+ }
+ }
+}
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneGraphBase.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneGraphBase.java
new file mode 100644
index 0000000..412ffbf
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneGraphBase.java
@@ -0,0 +1,61 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+
+import com.android.scenegraph.SceneManager;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.ProgramFragment;
+import android.renderscript.ProgramStore;
+import android.renderscript.ProgramVertex;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.RenderScript;
+import android.renderscript.RenderScriptGL;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public abstract class SceneGraphBase {
+ String mName;
+ Allocation mNameAlloc;
+ public void setName(String n) {
+ mName = n;
+ mNameAlloc = null;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ Allocation getNameAlloc(RenderScriptGL rs) {
+ if (mNameAlloc == null) {
+ mNameAlloc = SceneManager.getStringAsAllocation(rs, getName());
+ }
+ return mNameAlloc;
+ }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneManager.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneManager.java
new file mode 100644
index 0000000..f77f483
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/SceneManager.java
@@ -0,0 +1,355 @@
+/*
+ * 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.scenegraph;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Writer;
+import java.lang.Math;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.android.scenegraph.Camera;
+import com.android.scenegraph.MatrixTransform;
+import com.android.scenegraph.Scene;
+import com.android.testapp.R;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.AsyncTask;
+import android.renderscript.*;
+import android.renderscript.Allocation.MipmapControl;
+import android.renderscript.Mesh;
+import android.renderscript.RenderScriptGL;
+import android.renderscript.Type.Builder;
+import android.util.Log;
+import android.view.SurfaceHolder;
+
+/**
+ * @hide
+ */
+public class SceneManager extends SceneGraphBase {
+
+ HashMap<String, Allocation> mAllocationMap;
+
+ ScriptC_render mRenderLoop;
+ ScriptC mCameraScript;
+ ScriptC mLightScript;
+ ScriptC mObjectParamsScript;
+ ScriptC mFragmentParamsScript;
+ ScriptC mVertexParamsScript;
+ ScriptC mCullScript;
+ ScriptC_transform mTransformScript;
+ ScriptC_export mExportScript;
+
+ RenderScriptGL mRS;
+ Resources mRes;
+ Mesh mQuad;
+ int mWidth;
+ int mHeight;
+
+ Scene mActiveScene;
+ private static SceneManager sSceneManager;
+
+ private Allocation sDefault2D;
+ private Allocation sDefaultCube;
+
+ private static Allocation getDefault(boolean isCube) {
+ final int dimension = 4;
+ final int bytesPerPixel = 4;
+ int arraySize = dimension * dimension * bytesPerPixel;
+
+ RenderScriptGL rs = sSceneManager.mRS;
+ Type.Builder b = new Type.Builder(rs, Element.RGBA_8888(rs));
+ b.setX(dimension).setY(dimension);
+ if (isCube) {
+ b.setFaces(true);
+ arraySize *= 6;
+ }
+ Type bitmapType = b.create();
+
+ Allocation.MipmapControl mip = Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE;
+ int usage = Allocation.USAGE_GRAPHICS_TEXTURE;
+ Allocation defaultImage = Allocation.createTyped(rs, bitmapType, mip, usage);
+
+ byte imageData[] = new byte[arraySize];
+ defaultImage.copyFrom(imageData);
+ return defaultImage;
+ }
+
+ static Allocation getDefaultTex2D() {
+ if (sSceneManager == null) {
+ return null;
+ }
+ if (sSceneManager.sDefault2D == null) {
+ sSceneManager.sDefault2D = getDefault(false);
+ }
+ return sSceneManager.sDefault2D;
+ }
+
+ static Allocation getDefaultTexCube() {
+ if (sSceneManager == null) {
+ return null;
+ }
+ if (sSceneManager.sDefaultCube == null) {
+ sSceneManager.sDefaultCube = getDefault(true);
+ }
+ return sSceneManager.sDefaultCube;
+ }
+
+ public static boolean isSDCardPath(String path) {
+ int sdCardIndex = path.indexOf("sdcard/");
+ // We are looking for /sdcard/ or sdcard/
+ if (sdCardIndex == 0 || sdCardIndex == 1) {
+ return true;
+ }
+ sdCardIndex = path.indexOf("mnt/sdcard/");
+ if (sdCardIndex == 0 || sdCardIndex == 1) {
+ return true;
+ }
+ return false;
+ }
+
+ static Bitmap loadBitmap(String name, Resources res) {
+ InputStream is = null;
+ boolean loadFromSD = isSDCardPath(name);
+ try {
+ if (!loadFromSD) {
+ is = res.getAssets().open(name);
+ } else {
+ File f = new File(name);
+ is = new BufferedInputStream(new FileInputStream(f));
+ }
+ } catch (IOException e) {
+ Log.e("ImageLoaderTask", " Message: " + e.getMessage());
+ return null;
+ }
+
+ Bitmap b = BitmapFactory.decodeStream(is);
+ try {
+ is.close();
+ } catch (IOException e) {
+ Log.e("ImageLoaderTask", " Message: " + e.getMessage());
+ }
+ return b;
+ }
+
+ public static Allocation loadCubemap(String name, RenderScriptGL rs, Resources res) {
+ Bitmap b = loadBitmap(name, res);
+ if (b == null) {
+ return null;
+ }
+ return Allocation.createCubemapFromBitmap(rs, b,
+ MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+ Allocation.USAGE_GRAPHICS_TEXTURE);
+ }
+
+ public static Allocation loadTexture2D(String name, RenderScriptGL rs, Resources res) {
+ Bitmap b = loadBitmap(name, res);
+ if (b == null) {
+ return null;
+ }
+ return Allocation.createFromBitmap(rs, b,
+ Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+ Allocation.USAGE_GRAPHICS_TEXTURE);
+ }
+
+ public static ProgramStore BLEND_ADD_DEPTH_NONE(RenderScript rs) {
+ ProgramStore.Builder builder = new ProgramStore.Builder(rs);
+ builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
+ builder.setBlendFunc(ProgramStore.BlendSrcFunc.ONE, ProgramStore.BlendDstFunc.ONE);
+ builder.setDitherEnabled(false);
+ builder.setDepthMaskEnabled(false);
+ return builder.create();
+ }
+
+ static Allocation getStringAsAllocation(RenderScript rs, String str) {
+ if (str == null) {
+ return null;
+ }
+ if (str.length() == 0) {
+ return null;
+ }
+ byte[] allocArray = null;
+ byte[] nullChar = new byte[1];
+ nullChar[0] = 0;
+ try {
+ allocArray = str.getBytes("UTF-8");
+ Allocation alloc = Allocation.createSized(rs, Element.U8(rs),
+ allocArray.length + 1,
+ Allocation.USAGE_SCRIPT);
+ alloc.copy1DRangeFrom(0, allocArray.length, allocArray);
+ alloc.copy1DRangeFrom(allocArray.length, 1, nullChar);
+ return alloc;
+ }
+ catch (Exception e) {
+ throw new RSRuntimeException("Could not convert string to utf-8.");
+ }
+ }
+
+ static Allocation getCachedAlloc(String str) {
+ if (sSceneManager == null) {
+ throw new RuntimeException("Scene manager not initialized");
+ }
+ return sSceneManager.mAllocationMap.get(str);
+ }
+
+ static void cacheAlloc(String str, Allocation alloc) {
+ if (sSceneManager == null) {
+ throw new RuntimeException("Scene manager not initialized");
+ }
+ sSceneManager.mAllocationMap.put(str, alloc);
+ }
+
+ public static class SceneLoadedCallback implements Runnable {
+ public Scene mLoadedScene;
+ public String mName;
+ public void run() {
+ }
+ }
+
+ public Scene getActiveScene() {
+ return mActiveScene;
+ }
+
+ public void setActiveScene(Scene s) {
+ mActiveScene = s;
+
+ // Do some sanity checking
+ if (mActiveScene.getCameras().size() == 0) {
+ Matrix4f camPos = new Matrix4f();
+ camPos.translate(0, 0, 10);
+ MatrixTransform cameraTransform = new MatrixTransform();
+ cameraTransform.setName("_DefaultCameraTransform");
+ cameraTransform.setMatrix(camPos);
+ mActiveScene.appendTransform(cameraTransform);
+ Camera cam = new Camera();
+ cam.setName("_DefaultCamera");
+ cam.setTransform(cameraTransform);
+ mActiveScene.appendCamera(cam);
+ }
+ }
+
+ static RenderScriptGL getRS() {
+ if (sSceneManager == null) {
+ return null;
+ }
+ return sSceneManager.mRS;
+ }
+
+ static Resources getRes() {
+ if (sSceneManager == null) {
+ return null;
+ }
+ return sSceneManager.mRes;
+ }
+
+ public static SceneManager getInstance() {
+ if (sSceneManager == null) {
+ sSceneManager = new SceneManager();
+ }
+ return sSceneManager;
+ }
+
+ protected SceneManager() {
+ }
+
+ public void loadModel(String name, SceneLoadedCallback cb) {
+ ColladaScene scene = new ColladaScene(name, cb);
+ scene.init(mRS, mRes);
+ }
+
+ public Mesh getScreenAlignedQuad() {
+ if (mQuad != null) {
+ return mQuad;
+ }
+
+ Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS,
+ 3, Mesh.TriangleMeshBuilder.TEXTURE_0);
+
+ tmb.setTexture(0.0f, 1.0f);
+ tmb.addVertex(-1.0f, 1.0f, 1.0f);
+
+ tmb.setTexture(0.0f, 0.0f);
+ tmb.addVertex(-1.0f, -1.0f, 1.0f);
+
+ tmb.setTexture(1.0f, 0.0f);
+ tmb.addVertex(1.0f, -1.0f, 1.0f);
+
+ tmb.setTexture(1.0f, 1.0f);
+ tmb.addVertex(1.0f, 1.0f, 1.0f);
+
+ tmb.addTriangle(0, 1, 2);
+ tmb.addTriangle(2, 3, 0);
+
+ mQuad = tmb.create(true);
+ return mQuad;
+ }
+
+ public Renderable getRenderableQuad(String name, RenderState state) {
+ Renderable quad = new Renderable();
+ quad.setTransform(new MatrixTransform());
+ quad.setMesh(getScreenAlignedQuad());
+ quad.setName(name);
+ quad.setRenderState(state);
+ quad.setCullType(1);
+ return quad;
+ }
+
+ public void initRS(RenderScriptGL rs, Resources res, int w, int h) {
+ mRS = rs;
+ mRes = res;
+ mAllocationMap = new HashMap<String, Allocation>();
+
+ mExportScript = new ScriptC_export(rs, res, R.raw.export);
+
+ mTransformScript = new ScriptC_transform(rs, res, R.raw.transform);
+ mTransformScript.set_gTransformScript(mTransformScript);
+
+ mCameraScript = new ScriptC_camera(rs, res, R.raw.camera);
+ mLightScript = new ScriptC_light(rs, res, R.raw.light);
+ mObjectParamsScript = new ScriptC_object_params(rs, res, R.raw.object_params);
+ mFragmentParamsScript = new ScriptC_object_params(rs, res, R.raw.fragment_params);
+ mVertexParamsScript = new ScriptC_object_params(rs, res, R.raw.vertex_params);
+ mCullScript = new ScriptC_cull(rs, res, R.raw.cull);
+
+ mRenderLoop = new ScriptC_render(rs, res, R.raw.render);
+ mRenderLoop.set_gTransformScript(mTransformScript);
+ mRenderLoop.set_gCameraScript(mCameraScript);
+ mRenderLoop.set_gLightScript(mLightScript);
+ mRenderLoop.set_gObjectParamsScript(mObjectParamsScript);
+ mRenderLoop.set_gFragmentParamsScript(mFragmentParamsScript);
+ mRenderLoop.set_gVertexParamsScript(mVertexParamsScript);
+ mRenderLoop.set_gCullScript(mCullScript);
+
+ mRenderLoop.set_gPFSBackground(ProgramStore.BLEND_NONE_DEPTH_TEST(mRS));
+ }
+
+ public ScriptC getRenderLoop() {
+ return mRenderLoop;
+ }
+}
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Shader.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Shader.java
new file mode 100644
index 0000000..4975114
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Shader.java
@@ -0,0 +1,76 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import com.android.scenegraph.SceneGraphBase;
+import com.android.scenegraph.ShaderParam;
+
+import android.renderscript.*;
+import android.renderscript.ProgramFragment.Builder;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public abstract class Shader extends SceneGraphBase {
+ protected Type mPerObjConstants;
+ protected Type mPerShaderConstants;
+
+ protected HashMap<String, ShaderParam> mSourceParams;
+ protected ArrayList<String> mShaderTextureNames;
+ protected ArrayList<Program.TextureType > mShaderTextureTypes;
+ protected ArrayList<String> mTextureNames;
+ protected ArrayList<Program.TextureType > mTextureTypes;
+
+ protected Allocation mConstantBuffer;
+ protected ScriptField_ShaderParam_s mConstantBufferParams;
+
+ public Shader() {
+ mSourceParams = new HashMap<String, ShaderParam>();
+ mShaderTextureNames = new ArrayList<String>();
+ mShaderTextureTypes = new ArrayList<Program.TextureType>();
+ mTextureNames = new ArrayList<String>();
+ mTextureTypes = new ArrayList<Program.TextureType>();
+ }
+
+ public void appendSourceParams(ShaderParam p) {
+ mSourceParams.put(p.getParamName(), p);
+ }
+
+ public Type getObjectConstants() {
+ return mPerObjConstants;
+ }
+
+ public Type getShaderConstants() {
+ return mPerObjConstants;
+ }
+
+ void linkConstants(RenderScriptGL rs) {
+ if (mPerShaderConstants == null) {
+ return;
+ }
+
+ Element constElem = mPerShaderConstants.getElement();
+ mConstantBufferParams = ShaderParam.fillInParams(constElem, mSourceParams, null);
+
+ mConstantBuffer = Allocation.createTyped(rs, mPerShaderConstants);
+ }
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ShaderParam.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ShaderParam.java
new file mode 100644
index 0000000..8dea535
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/ShaderParam.java
@@ -0,0 +1,162 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import com.android.scenegraph.SceneManager;
+import com.android.scenegraph.Transform;
+
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.ProgramFragment;
+import android.renderscript.ProgramStore;
+import android.renderscript.ProgramVertex;
+import android.renderscript.RenderScriptGL;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public abstract class ShaderParam extends SceneGraphBase {
+
+ static final String cameraPos = "cameraPos";
+ static final String cameraDir = "cameraDir";
+
+ static final String lightColor = "lightColor";
+ static final String lightPos = "lightPos";
+ static final String lightDir = "lightDir";
+
+ static final String view = "view";
+ static final String proj = "proj";
+ static final String viewProj = "viewProj";
+ static final String model = "model";
+ static final String modelView = "modelView";
+ static final String modelViewProj = "modelViewProj";
+
+ static final long sMaxTimeStamp = 0xffffffffL;
+
+ ScriptField_ShaderParamData_s.Item mData;
+ ScriptField_ShaderParamData_s mField;
+
+ String mParamName;
+ Camera mCamera;
+
+ static ScriptField_ShaderParam_s fillInParams(Element constantElem,
+ HashMap<String, ShaderParam> sourceParams,
+ Transform transform) {
+ RenderScriptGL rs = SceneManager.getRS();
+ ArrayList<ScriptField_ShaderParam_s.Item> paramList;
+ paramList = new ArrayList<ScriptField_ShaderParam_s.Item>();
+
+ int subElemCount = constantElem.getSubElementCount();
+ for (int i = 0; i < subElemCount; i ++) {
+ String inputName = constantElem.getSubElementName(i);
+ int offset = constantElem.getSubElementOffsetBytes(i);
+
+ ShaderParam matchingParam = sourceParams.get(inputName);
+ Element subElem = constantElem.getSubElement(i);
+ // Make one if it's not there
+ if (matchingParam == null) {
+ if (subElem.getDataType() == Element.DataType.FLOAT_32) {
+ matchingParam = new Float4Param(inputName);
+ } else if (subElem.getDataType() == Element.DataType.MATRIX_4X4) {
+ TransformParam trParam = new TransformParam(inputName);
+ trParam.setTransform(transform);
+ matchingParam = trParam;
+ }
+ }
+ ScriptField_ShaderParam_s.Item paramRS = new ScriptField_ShaderParam_s.Item();
+ paramRS.bufferOffset = offset;
+ paramRS.transformTimestamp = 0;
+ paramRS.dataTimestamp = 0;
+ paramRS.data = matchingParam.getRSData().getAllocation();
+ if (subElem.getDataType() == Element.DataType.FLOAT_32) {
+ paramRS.float_vecSize = subElem.getVectorSize();
+ }
+
+ paramList.add(paramRS);
+ }
+
+ ScriptField_ShaderParam_s rsParams = null;
+ int paramCount = paramList.size();
+ if (paramCount != 0) {
+ rsParams = new ScriptField_ShaderParam_s(rs, paramCount);
+ for (int i = 0; i < paramCount; i++) {
+ rsParams.set(paramList.get(i), i, false);
+ }
+ rsParams.copyAll();
+ }
+ return rsParams;
+ }
+
+ public ShaderParam(String name) {
+ mParamName = name;
+ mData = new ScriptField_ShaderParamData_s.Item();
+ }
+
+ public String getParamName() {
+ return mParamName;
+ }
+
+ public void setCamera(Camera c) {
+ mCamera = c;
+ if (mField != null) {
+ mData.camera = mCamera.getRSData().getAllocation();
+ mField.set_camera(0, mData.camera, true);
+ }
+ }
+
+ protected void incTimestamp() {
+ if (mField != null) {
+ mData.timestamp ++;
+ mData.timestamp %= sMaxTimeStamp;
+ mField.set_timestamp(0, mData.timestamp, true);
+ }
+ }
+
+ abstract void initLocalData();
+
+ public ScriptField_ShaderParamData_s getRSData() {
+ if (mField != null) {
+ return mField;
+ }
+
+ RenderScriptGL rs = SceneManager.getRS();
+ mField = new ScriptField_ShaderParamData_s(rs, 1);
+
+ if (mParamName != null) {
+ mData.paramName = SceneManager.getCachedAlloc(mParamName);
+ if (mData.paramName == null) {
+ mData.paramName = SceneManager.getStringAsAllocation(rs, mParamName);
+ SceneManager.cacheAlloc(mParamName, mData.paramName);
+ }
+ }
+ initLocalData();
+ mData.timestamp = 1;
+
+ mField.set(mData, 0, true);
+ return mField;
+ }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Texture2D.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Texture2D.java
new file mode 100644
index 0000000..8fae9d9
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Texture2D.java
@@ -0,0 +1,97 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+
+import com.android.scenegraph.SceneManager;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class Texture2D extends TextureBase {
+ String mFileName;
+ String mFileDir;
+
+ public Texture2D() {
+ super(ScriptC_export.const_TextureType_TEXTURE_2D);
+ }
+
+ public Texture2D(Allocation tex) {
+ super(ScriptC_export.const_TextureType_TEXTURE_2D);
+ setTexture(tex);
+ }
+
+ public void setFileDir(String dir) {
+ mFileDir = dir;
+ }
+
+ public void setFileName(String file) {
+ mFileName = file;
+ }
+
+ public String getFileName() {
+ return mFileName;
+ }
+
+ public void setTexture(Allocation tex) {
+ mData.texture = tex != null ? tex : SceneManager.getDefaultTex2D();
+ if (mField != null) {
+ mField.set_texture(0, mData.texture, true);
+ }
+ }
+
+ void load() {
+ RenderScriptGL rs = SceneManager.getRS();
+ Resources res = SceneManager.getRes();
+ String shortName = mFileName.substring(mFileName.lastIndexOf('/') + 1);
+ setTexture(SceneManager.loadTexture2D(mFileDir + shortName, rs, res));
+ }
+
+ ScriptField_Texture_s getRsData(boolean loadNow) {
+ if (mField != null) {
+ return mField;
+ }
+
+ RenderScriptGL rs = SceneManager.getRS();
+ Resources res = SceneManager.getRes();
+ if (rs == null || res == null) {
+ return null;
+ }
+
+ mField = new ScriptField_Texture_s(rs, 1);
+
+ if (loadNow) {
+ load();
+ } else {
+ mData.texture = SceneManager.getDefaultTex2D();
+ new SingleImageLoaderTask().execute(this);
+ }
+
+ mField.set(mData, 0, true);
+ return mField;
+ }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureBase.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureBase.java
new file mode 100644
index 0000000..ba49d4e
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureBase.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.scenegraph;
+
+import java.lang.Math;
+
+import com.android.scenegraph.SceneManager;
+import android.os.AsyncTask;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public abstract class TextureBase extends SceneGraphBase {
+
+ class SingleImageLoaderTask extends AsyncTask<TextureBase, Void, Boolean> {
+ protected Boolean doInBackground(TextureBase... objects) {
+ TextureBase tex = objects[0];
+ tex.load();
+ return new Boolean(true);
+ }
+ protected void onPostExecute(Boolean result) {
+ }
+ }
+
+ ScriptField_Texture_s.Item mData;
+ ScriptField_Texture_s mField;
+ TextureBase(int type) {
+ mData = new ScriptField_Texture_s.Item();
+ mData.type = type;
+ }
+
+ protected Allocation mRsTexture;
+ abstract ScriptField_Texture_s getRsData(boolean loadNow);
+ abstract void load();
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureCube.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureCube.java
new file mode 100644
index 0000000..12c81c2
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureCube.java
@@ -0,0 +1,104 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+
+import com.android.scenegraph.SceneManager;
+import com.android.scenegraph.TextureBase;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class TextureCube extends TextureBase {
+ String mFileName;
+ String mFileDir;
+
+ public TextureCube() {
+ super(ScriptC_export.const_TextureType_TEXTURE_CUBE);
+ }
+
+ public TextureCube(Allocation tex) {
+ super(ScriptC_export.const_TextureType_TEXTURE_CUBE);
+ setTexture(tex);
+ }
+
+ public TextureCube(String dir, String file) {
+ super(ScriptC_export.const_TextureType_TEXTURE_CUBE);
+ setFileDir(dir);
+ setFileName(file);
+ }
+
+ public void setFileDir(String dir) {
+ mFileDir = dir;
+ }
+
+ public void setFileName(String file) {
+ mFileName = file;
+ }
+
+ public String getFileName() {
+ return mFileName;
+ }
+
+ public void setTexture(Allocation tex) {
+ mData.texture = tex != null ? tex : SceneManager.getDefaultTexCube();
+ if (mField != null) {
+ mField.set_texture(0, mData.texture, true);
+ }
+ }
+
+ void load() {
+ RenderScriptGL rs = SceneManager.getRS();
+ Resources res = SceneManager.getRes();
+ String shortName = mFileName.substring(mFileName.lastIndexOf('/') + 1);
+ setTexture(SceneManager.loadCubemap(mFileDir + shortName, rs, res));
+ }
+
+ ScriptField_Texture_s getRsData(boolean loadNow) {
+ if (mField != null) {
+ return mField;
+ }
+
+ RenderScriptGL rs = SceneManager.getRS();
+ Resources res = SceneManager.getRes();
+ if (rs == null || res == null) {
+ return null;
+ }
+
+ mField = new ScriptField_Texture_s(rs, 1);
+
+ if (loadNow) {
+ load();
+ } else {
+ mData.texture = SceneManager.getDefaultTexCube();
+ new SingleImageLoaderTask().execute(this);
+ }
+
+ mField.set(mData, 0, true);
+ return mField;
+ }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureParam.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureParam.java
new file mode 100644
index 0000000..e656ed2
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureParam.java
@@ -0,0 +1,67 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+
+import android.graphics.Camera;
+import android.renderscript.RenderScriptGL;
+import android.renderscript.Float4;
+import android.renderscript.Matrix4f;
+import android.renderscript.ProgramFragment;
+import android.renderscript.ProgramStore;
+import android.renderscript.ProgramVertex;
+import android.renderscript.Element;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class TextureParam extends ShaderParam {
+
+ TextureBase mTexture;
+
+ public TextureParam(String name) {
+ super(name);
+ }
+
+ public TextureParam(String name, TextureBase t) {
+ super(name);
+ setTexture(t);
+ }
+
+ public void setTexture(TextureBase t) {
+ mTexture = t;
+ }
+
+ public TextureBase getTexture() {
+ return mTexture;
+ }
+
+ void initLocalData() {
+ mData.type = ScriptC_export.const_ShaderParam_TEXTURE;
+ if (mTexture != null) {
+ mData.texture = mTexture.getRsData(false).getAllocation();
+ }
+ }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureRenderTarget.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureRenderTarget.java
new file mode 100644
index 0000000..6aa29a5
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TextureRenderTarget.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.scenegraph;
+
+import java.lang.Math;
+
+import com.android.scenegraph.SceneManager;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class TextureRenderTarget extends TextureBase {
+ public TextureRenderTarget() {
+ super(ScriptC_export.const_TextureType_TEXTURE_RENDER_TARGET);
+ }
+
+ public TextureRenderTarget(Allocation tex) {
+ super(ScriptC_export.const_TextureType_TEXTURE_RENDER_TARGET);
+ setTexture(tex);
+ }
+
+ public void setTexture(Allocation tex) {
+ mData.texture = tex;
+ if (mField != null) {
+ mField.set_texture(0, mData.texture, true);
+ }
+ }
+
+ void load() {
+ }
+
+ ScriptField_Texture_s getRsData(boolean loadNow) {
+ if (mField != null) {
+ return mField;
+ }
+
+ RenderScriptGL rs = SceneManager.getRS();
+ if (rs == null) {
+ return null;
+ }
+
+ mField = new ScriptField_Texture_s(rs, 1);
+ mField.set(mData, 0, true);
+ return mField;
+ }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Transform.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Transform.java
new file mode 100644
index 0000000..8180bd0
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/Transform.java
@@ -0,0 +1,98 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+
+import android.renderscript.*;
+import android.renderscript.Matrix4f;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public abstract class Transform extends SceneGraphBase {
+ Transform mParent;
+ ArrayList<Transform> mChildren;
+
+ ScriptField_SgTransform mField;
+ ScriptField_SgTransform.Item mTransformData;
+
+ public Transform() {
+ mChildren = new ArrayList<Transform>();
+ mParent = null;
+ }
+
+ public void appendChild(Transform t) {
+ mChildren.add(t);
+ t.mParent = this;
+ updateRSChildData(true);
+ }
+
+ abstract void initLocalData();
+
+ void updateRSChildData(boolean copyData) {
+ if (mField == null) {
+ return;
+ }
+ RenderScriptGL rs = SceneManager.getRS();
+ if (mChildren.size() != 0) {
+ Allocation childRSData = Allocation.createSized(rs, Element.ALLOCATION(rs),
+ mChildren.size());
+ mTransformData.children = childRSData;
+
+ Allocation[] childrenAllocs = new Allocation[mChildren.size()];
+ for (int i = 0; i < mChildren.size(); i ++) {
+ Transform child = mChildren.get(i);
+ childrenAllocs[i] = child.getRSData().getAllocation();
+ }
+ childRSData.copyFrom(childrenAllocs);
+ }
+ if (copyData) {
+ mField.set(mTransformData, 0, true);
+ }
+ }
+
+ ScriptField_SgTransform getRSData() {
+ if (mField != null) {
+ return mField;
+ }
+
+ RenderScriptGL rs = SceneManager.getRS();
+ if (rs == null) {
+ return null;
+ }
+ mField = new ScriptField_SgTransform(rs, 1);
+
+ mTransformData = new ScriptField_SgTransform.Item();
+ mTransformData.name = getNameAlloc(rs);
+ mTransformData.isDirty = 1;
+ mTransformData.timestamp = 1;
+
+ initLocalData();
+ updateRSChildData(false);
+
+ mField.set(mTransformData, 0, true);
+ return mField;
+ }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TransformParam.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TransformParam.java
new file mode 100644
index 0000000..d120d5d
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/TransformParam.java
@@ -0,0 +1,85 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+
+import android.renderscript.RenderScriptGL;
+import android.renderscript.Matrix4f;
+import android.renderscript.ProgramFragment;
+import android.renderscript.ProgramStore;
+import android.renderscript.ProgramVertex;
+import android.renderscript.Element;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class TransformParam extends ShaderParam {
+
+ Transform mTransform;
+ LightBase mLight;
+
+ public TransformParam(String name) {
+ super(name);
+ }
+
+ public void setTransform(Transform t) {
+ mTransform = t;
+ if (mField != null && mTransform != null) {
+ mData.transform = mTransform.getRSData().getAllocation();
+ }
+ incTimestamp();
+ }
+
+ int getTypeFromName() {
+ int paramType = ScriptC_export.const_ShaderParam_TRANSFORM_DATA;
+ if (mParamName.equalsIgnoreCase(view)) {
+ paramType = ScriptC_export.const_ShaderParam_TRANSFORM_VIEW;
+ } else if(mParamName.equalsIgnoreCase(proj)) {
+ paramType = ScriptC_export.const_ShaderParam_TRANSFORM_PROJ;
+ } else if(mParamName.equalsIgnoreCase(viewProj)) {
+ paramType = ScriptC_export.const_ShaderParam_TRANSFORM_VIEW_PROJ;
+ } else if(mParamName.equalsIgnoreCase(model)) {
+ paramType = ScriptC_export.const_ShaderParam_TRANSFORM_MODEL;
+ } else if(mParamName.equalsIgnoreCase(modelView)) {
+ paramType = ScriptC_export.const_ShaderParam_TRANSFORM_MODEL_VIEW;
+ } else if(mParamName.equalsIgnoreCase(modelViewProj)) {
+ paramType = ScriptC_export.const_ShaderParam_TRANSFORM_MODEL_VIEW_PROJ;
+ }
+ return paramType;
+ }
+
+ void initLocalData() {
+ mData.type = getTypeFromName();
+ if (mTransform != null) {
+ mData.transform = mTransform.getRSData().getAllocation();
+ }
+ if (mCamera != null) {
+ mData.camera = mCamera.getRSData().getAllocation();
+ }
+ if (mLight != null) {
+ mData.light = mLight.getRSData().getAllocation();
+ }
+ }
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/VertexShader.java b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/VertexShader.java
new file mode 100644
index 0000000..f7d0e6d
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/VertexShader.java
@@ -0,0 +1,108 @@
+/*
+ * 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.scenegraph;
+
+import java.lang.Math;
+import java.util.ArrayList;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class VertexShader extends Shader {
+ ProgramVertex mProgram;
+ ScriptField_VertexShader_s mField;
+
+ public static class Builder {
+ VertexShader mShader;
+ ProgramVertex.Builder mBuilder;
+
+ public Builder(RenderScriptGL rs) {
+ mShader = new VertexShader();
+ mBuilder = new ProgramVertex.Builder(rs);
+ }
+
+ public Builder setShader(Resources resources, int resourceID) {
+ mBuilder.setShader(resources, resourceID);
+ return this;
+ }
+
+ public Builder setObjectConst(Type type) {
+ mShader.mPerObjConstants = type;
+ return this;
+ }
+
+ public Builder setShaderConst(Type type) {
+ mShader.mPerShaderConstants = type;
+ return this;
+ }
+
+ public Builder addInput(Element e) {
+ mBuilder.addInput(e);
+ return this;
+ }
+
+ public VertexShader create() {
+ if (mShader.mPerShaderConstants != null) {
+ mBuilder.addConstant(mShader.mPerShaderConstants);
+ }
+ if (mShader.mPerObjConstants != null) {
+ mBuilder.addConstant(mShader.mPerObjConstants);
+ }
+ mShader.mProgram = mBuilder.create();
+ return mShader;
+ }
+ }
+
+ public ProgramVertex getProgram() {
+ return mProgram;
+ }
+
+ ScriptField_VertexShader_s getRSData() {
+ if (mField != null) {
+ return mField;
+ }
+
+ RenderScriptGL rs = SceneManager.getRS();
+ Resources res = SceneManager.getRes();
+ if (rs == null || res == null) {
+ return null;
+ }
+
+ ScriptField_VertexShader_s.Item item = new ScriptField_VertexShader_s.Item();
+ item.program = mProgram;
+
+ linkConstants(rs);
+ if (mPerShaderConstants != null) {
+ item.shaderConst = mConstantBuffer;
+ item.shaderConstParams = mConstantBufferParams.getAllocation();
+ mProgram.bindConstants(item.shaderConst, 0);
+ }
+
+ item.objectConstIndex = -1;
+ if (mPerObjConstants != null) {
+ item.objectConstIndex = mPerShaderConstants != null ? 1 : 0;
+ }
+
+ mField = new ScriptField_VertexShader_s(rs, 1);
+ mField.set(item, 0, true);
+ return mField;
+ }
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/camera.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/camera.rs
new file mode 100644
index 0000000..dc0a885
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/camera.rs
@@ -0,0 +1,66 @@
+// 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.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.scenegraph)
+
+//#define DEBUG_CAMERA
+#include "scenegraph_objects.rsh"
+
+void root(const rs_allocation *v_in, rs_allocation *v_out, const float *usrData) {
+
+ SgCamera *cam = (SgCamera *)rsGetElementAt(*v_in, 0);
+ float aspect = *usrData;
+ if (cam->aspect != aspect) {
+ cam->isDirty = 1;
+ cam->aspect = aspect;
+ }
+ if (cam->isDirty) {
+ rsMatrixLoadPerspective(&cam->proj, cam->horizontalFOV, cam->aspect, cam->near, cam->far);
+ }
+
+ const SgTransform *camTransform = (const SgTransform *)rsGetElementAt(cam->transformMatrix, 0);
+ //rsDebug("Camera stamp", cam->transformTimestamp);
+ //rsDebug("Transform stamp", camTransform->timestamp);
+ if (camTransform->timestamp != cam->transformTimestamp || cam->isDirty) {
+ cam->isDirty = 1;
+ rs_matrix4x4 camPosMatrix;
+ rsMatrixLoad(&camPosMatrix, &camTransform->globalMat);
+ float4 zero = {0.0f, 0.0f, 0.0f, 1.0f};
+ cam->position = rsMatrixMultiply(&camPosMatrix, zero);
+
+ rsMatrixInverse(&camPosMatrix);
+ rsMatrixLoad(&cam->view, &camPosMatrix);
+
+ rsMatrixLoad(&cam->viewProj, &cam->proj);
+ rsMatrixMultiply(&cam->viewProj, &cam->view);
+
+ rsExtractFrustumPlanes(&cam->viewProj,
+ &cam->frustumPlanes[0], &cam->frustumPlanes[1],
+ &cam->frustumPlanes[2], &cam->frustumPlanes[3],
+ &cam->frustumPlanes[3], &cam->frustumPlanes[4]);
+ }
+
+ if (cam->isDirty) {
+ cam->timestamp ++;
+ }
+
+ cam->isDirty = 0;
+ cam->transformTimestamp = camTransform->timestamp;
+
+#ifdef DEBUG_CAMERA
+ printCameraInfo(cam);
+#endif //DEBUG_CAMERA
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/cull.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/cull.rs
new file mode 100644
index 0000000..024e026
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/cull.rs
@@ -0,0 +1,86 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.scenegraph)
+
+#include "scenegraph_objects.rsh"
+
+static void getTransformedSphere(SgRenderable *obj) {
+ obj->worldBoundingSphere = obj->boundingSphere;
+ obj->worldBoundingSphere.w = 1.0f;
+ const SgTransform *objTransform = (const SgTransform *)rsGetElementAt(obj->transformMatrix, 0);
+ obj->worldBoundingSphere = rsMatrixMultiply(&objTransform->globalMat, obj->worldBoundingSphere);
+
+ const float4 unitVec = {0.57735f, 0.57735f, 0.57735f, 0.0f};
+ float4 scaledVec = rsMatrixMultiply(&objTransform->globalMat, unitVec);
+ scaledVec.w = 0.0f;
+ obj->worldBoundingSphere.w = obj->boundingSphere.w * length(scaledVec);
+}
+
+static bool frustumCulled(SgRenderable *obj, SgCamera *cam) {
+ if (!obj->bVolInitialized) {
+ float minX, minY, minZ, maxX, maxY, maxZ;
+ rsgMeshComputeBoundingBox(obj->mesh,
+ &minX, &minY, &minZ,
+ &maxX, &maxY, &maxZ);
+ //rsDebug("min", minX, minY, minZ);
+ //rsDebug("max", maxX, maxY, maxZ);
+ float4 sphere;
+ sphere.x = (maxX + minX) * 0.5f;
+ sphere.y = (maxY + minY) * 0.5f;
+ sphere.z = (maxZ + minZ) * 0.5f;
+ float3 radius;
+ radius.x = (maxX - sphere.x);
+ radius.y = (maxY - sphere.y);
+ radius.z = (maxZ - sphere.z);
+
+ sphere.w = length(radius);
+ obj->boundingSphere = sphere;
+ obj->bVolInitialized = 1;
+ //rsDebug("Sphere", sphere);
+ }
+
+ getTransformedSphere(obj);
+
+ return !rsIsSphereInFrustum(&obj->worldBoundingSphere,
+ &cam->frustumPlanes[0], &cam->frustumPlanes[1],
+ &cam->frustumPlanes[2], &cam->frustumPlanes[3],
+ &cam->frustumPlanes[4], &cam->frustumPlanes[5]);
+}
+
+
+void root(rs_allocation *v_out, const void *usrData) {
+
+ SgRenderable *drawable = (SgRenderable *)rsGetElementAt(*v_out, 0);
+ const SgCamera *camera = (const SgCamera*)usrData;
+
+ drawable->isVisible = 0;
+ // Not loaded yet
+ if (!rsIsObject(drawable->mesh) || drawable->cullType == CULL_ALWAYS) {
+ return;
+ }
+
+ // check to see if we are culling this object and if it's
+ // outside the frustum
+ if (drawable->cullType == CULL_FRUSTUM && frustumCulled(drawable, (SgCamera*)camera)) {
+#ifdef DEBUG_RENDERABLES
+ rsDebug("Culled", drawable);
+ printName(drawable->name);
+#endif // DEBUG_RENDERABLES
+ return;
+ }
+ drawable->isVisible = 1;
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/export.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/export.rs
new file mode 100644
index 0000000..b438a43
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/export.rs
@@ -0,0 +1,61 @@
+// 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.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.scenegraph)
+
+// The sole purpose of this script is to have various structs exposed
+// so that java reflected classes are generated
+#include "scenegraph_objects.rsh"
+
+// Export our native constants to java so that we don't have parallel definitions
+const int ShaderParam_FLOAT4_DATA = SHADER_PARAM_FLOAT4_DATA;
+const int ShaderParam_TRANSFORM_DATA = SHADER_PARAM_TRANSFORM_DATA;
+const int ShaderParam_TRANSFORM_MODEL = SHADER_PARAM_TRANSFORM_MODEL;
+
+const int ShaderParam_FLOAT4_CAMERA_POS = SHADER_PARAM_FLOAT4_CAMERA_POS;
+const int ShaderParam_FLOAT4_CAMERA_DIR = SHADER_PARAM_FLOAT4_CAMERA_DIR;
+const int ShaderParam_TRANSFORM_VIEW = SHADER_PARAM_TRANSFORM_VIEW;
+const int ShaderParam_TRANSFORM_PROJ = SHADER_PARAM_TRANSFORM_PROJ;
+const int ShaderParam_TRANSFORM_VIEW_PROJ = SHADER_PARAM_TRANSFORM_VIEW_PROJ;
+const int ShaderParam_TRANSFORM_MODEL_VIEW = SHADER_PARAM_TRANSFORM_MODEL_VIEW;
+const int ShaderParam_TRANSFORM_MODEL_VIEW_PROJ = SHADER_PARAM_TRANSFORM_MODEL_VIEW_PROJ;
+
+const int ShaderParam_FLOAT4_LIGHT_COLOR = SHADER_PARAM_FLOAT4_LIGHT_COLOR;
+const int ShaderParam_FLOAT4_LIGHT_POS = SHADER_PARAM_FLOAT4_LIGHT_POS;
+const int ShaderParam_FLOAT4_LIGHT_DIR = SHADER_PARAM_FLOAT4_LIGHT_DIR;
+
+const int ShaderParam_TEXTURE = SHADER_PARAM_TEXTURE;
+
+const int Transform_TRANSLATE = TRANSFORM_TRANSLATE;
+const int Transform_ROTATE = TRANSFORM_ROTATE;
+const int Transform_SCALE = TRANSFORM_SCALE;
+
+const int TextureType_TEXTURE_2D = TEXTURE_2D;
+const int TextureType_TEXTURE_CUBE = TEXTURE_CUBE;
+const int TextureType_TEXTURE_RENDER_TARGET = TEXTURE_RENDER_TARGET;
+
+SgTransform *exportPtr;
+SgTransformComponent *componentPtr;
+SgRenderState *sExport;
+SgRenderable *drExport;
+SgRenderPass *pExport;
+SgCamera *exportPtrCam;
+SgLight *exportPtrLight;
+SgShaderParam *spExport;
+SgShaderParamData *spDataExport;
+SgVertexShader *pvExport;
+SgFragmentShader *pfExport;
+SgTexture *texExport;
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/fragment_params.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/fragment_params.rs
new file mode 100644
index 0000000..7202285
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/fragment_params.rs
@@ -0,0 +1,30 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.scenegraph)
+
+#include "scenegraph_objects.rsh"
+
+//#define DEBUG_PARAMS
+
+#include "params.rsh"
+
+void root(rs_allocation *v_out, const void *usrData) {
+ SgFragmentShader *shader = (SgFragmentShader *)rsGetElementAt(*v_out, 0);
+ const SgCamera *camera = (const SgCamera*)usrData;
+ processAllParams(shader->shaderConst, shader->shaderConstParams, camera);
+ processTextureParams(shader);
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/light.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/light.rs
new file mode 100644
index 0000000..e11979f
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/light.rs
@@ -0,0 +1,33 @@
+// 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.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.scenegraph)
+
+//#define DEBUG_LIGHT
+#include "scenegraph_objects.rsh"
+
+void root(const rs_allocation *v_in, rs_allocation *v_out) {
+
+ SgLight *light = (SgLight *)rsGetElementAt(*v_in, 0);
+ const SgTransform *lTransform = (const SgTransform *)rsGetElementAt(light->transformMatrix, 0);
+
+ float4 zero = {0.0f, 0.0f, 0.0f, 1.0f};
+ light->position = rsMatrixMultiply(&lTransform->globalMat, zero);
+
+#ifdef DEBUG_LIGHT
+ printLightInfo(light);
+#endif //DEBUG_LIGHT
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/object_params.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/object_params.rs
new file mode 100644
index 0000000..0d524a6
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/object_params.rs
@@ -0,0 +1,36 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.scenegraph)
+
+#include "scenegraph_objects.rsh"
+
+//#define DEBUG_PARAMS
+
+#include "params.rsh"
+
+void root(rs_allocation *v_out, const void *usrData) {
+
+ SgRenderable *drawable = (SgRenderable *)rsGetElementAt(*v_out, 0);
+ // Visibility flag was set earlier in the cull stage
+ if (!drawable->isVisible) {
+ return;
+ }
+
+ const SgCamera *camera = (const SgCamera*)usrData;
+ processAllParams(drawable->pf_const, drawable->pf_constParams, camera);
+ processAllParams(drawable->pv_const, drawable->pv_constParams, camera);
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/params.rsh b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/params.rsh
new file mode 100644
index 0000000..575794b
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/params.rsh
@@ -0,0 +1,193 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.scenegraph)
+
+#include "scenegraph_objects.rsh"
+
+//#define DEBUG_PARAMS
+static void debugParam(SgShaderParam *p, SgShaderParamData *pData) {
+ rsDebug("____________ Param ____________", p);
+ printName(pData->paramName);
+ rsDebug("bufferOffset", p->bufferOffset);
+ rsDebug("type ", pData->type);
+ rsDebug("data timestamp ", pData->timestamp);
+ rsDebug("param timestamp", p->dataTimestamp);
+
+ const SgTransform *pTransform = NULL;
+ if (rsIsObject(pData->transform)) {
+ pTransform = (const SgTransform *)rsGetElementAt(pData->transform, 0);
+
+ rsDebug("transform", pTransform);
+ printName(pTransform->name);
+ rsDebug("timestamp", pTransform->timestamp);
+ rsDebug("param timestamp", p->transformTimestamp);
+ }
+
+ const SgLight *pLight = NULL;
+ if (rsIsObject(pData->light)) {
+ pLight = (const SgLight *)rsGetElementAt(pData->light, 0);
+ printLightInfo(pLight);
+ }
+}
+
+
+static void writeFloatData(float *ptr, const float4 *input, uint32_t vecSize) {
+#ifdef DEBUG_PARAMS
+ rsDebug("Writing value ", *input);
+ rsDebug("Writing vec size ", vecSize);
+#endif // DEBUG_PARAMS
+
+ switch (vecSize) {
+ case 1:
+ *ptr = input->x;
+ break;
+ case 2:
+ *((float2*)ptr) = (*input).xy;
+ break;
+ case 3:
+ *((float3*)ptr) = (*input).xyz;
+ break;
+ case 4:
+ *((float4*)ptr) = *input;
+ break;
+ }
+}
+
+static bool processParam(SgShaderParam *p, SgShaderParamData *pData,
+ uint8_t *constantBuffer,
+ const SgCamera *currentCam,
+ SgFragmentShader *shader) {
+ bool isDataOnly = (pData->type > SHADER_PARAM_DATA_ONLY);
+ const SgTransform *pTransform = NULL;
+ if (rsIsObject(pData->transform)) {
+ pTransform = (const SgTransform *)rsGetElementAt(pData->transform, 0);
+ }
+
+ if (isDataOnly) {
+ // If we are a transform param and our transform is unchanged, nothing to do
+ if (pTransform) {
+ if (p->transformTimestamp == pTransform->timestamp) {
+ return false;
+ }
+ p->transformTimestamp = pTransform->timestamp;
+ } else {
+ if (p->dataTimestamp == pData->timestamp) {
+ return false;
+ }
+ p->dataTimestamp = pData->timestamp;
+ }
+ }
+
+ const SgLight *pLight = NULL;
+ if (rsIsObject(pData->light)) {
+ pLight = (const SgLight *)rsGetElementAt(pData->light, 0);
+ }
+
+ uint8_t *dataPtr = NULL;
+ const SgTexture *tex = NULL;
+ if (pData->type == SHADER_PARAM_TEXTURE) {
+ tex = rsGetElementAt(pData->texture, 0);
+ } else {
+ dataPtr = constantBuffer + p->bufferOffset;
+ }
+
+ switch (pData->type) {
+ case SHADER_PARAM_TEXTURE:
+ rsgBindTexture(shader->program, p->bufferOffset, tex->texture);
+ break;
+ case SHADER_PARAM_FLOAT4_DATA:
+ writeFloatData((float*)dataPtr, &pData->float_value, p->float_vecSize);
+ break;
+ case SHADER_PARAM_FLOAT4_CAMERA_POS:
+ writeFloatData((float*)dataPtr, ¤tCam->position, p->float_vecSize);
+ break;
+ case SHADER_PARAM_FLOAT4_CAMERA_DIR: break;
+ case SHADER_PARAM_FLOAT4_LIGHT_COLOR:
+ writeFloatData((float*)dataPtr, &pLight->color, p->float_vecSize);
+ break;
+ case SHADER_PARAM_FLOAT4_LIGHT_POS:
+ writeFloatData((float*)dataPtr, &pLight->position, p->float_vecSize);
+ break;
+ case SHADER_PARAM_FLOAT4_LIGHT_DIR: break;
+
+ case SHADER_PARAM_TRANSFORM_DATA:
+ rsMatrixLoad((rs_matrix4x4*)dataPtr, &pTransform->globalMat);
+ break;
+ case SHADER_PARAM_TRANSFORM_VIEW:
+ rsMatrixLoad((rs_matrix4x4*)dataPtr, ¤tCam->view);
+ break;
+ case SHADER_PARAM_TRANSFORM_PROJ:
+ rsMatrixLoad((rs_matrix4x4*)dataPtr, ¤tCam->proj);
+ break;
+ case SHADER_PARAM_TRANSFORM_VIEW_PROJ:
+ rsMatrixLoad((rs_matrix4x4*)dataPtr, ¤tCam->viewProj);
+ break;
+ case SHADER_PARAM_TRANSFORM_MODEL:
+ rsMatrixLoad((rs_matrix4x4*)dataPtr, &pTransform->globalMat);
+ break;
+ case SHADER_PARAM_TRANSFORM_MODEL_VIEW:
+ rsMatrixLoad((rs_matrix4x4*)dataPtr, ¤tCam->view);
+ rsMatrixLoadMultiply((rs_matrix4x4*)dataPtr,
+ (rs_matrix4x4*)dataPtr,
+ &pTransform->globalMat);
+ break;
+ case SHADER_PARAM_TRANSFORM_MODEL_VIEW_PROJ:
+ rsMatrixLoad((rs_matrix4x4*)dataPtr, ¤tCam->viewProj);
+ rsMatrixLoadMultiply((rs_matrix4x4*)dataPtr,
+ (rs_matrix4x4*)dataPtr,
+ &pTransform->globalMat);
+ break;
+ }
+ return true;
+}
+
+static void processAllParams(rs_allocation shaderConst,
+ rs_allocation allParams,
+ const SgCamera *camera) {
+ if (rsIsObject(shaderConst)) {
+ uint8_t *constantBuffer = (uint8_t*)rsGetElementAt(shaderConst, 0);
+
+ int numParams = 0;
+ if (rsIsObject(allParams)) {
+ numParams = rsAllocationGetDimX(allParams);
+ }
+ bool updated = false;
+ for (int i = 0; i < numParams; i ++) {
+ SgShaderParam *current = (SgShaderParam*)rsGetElementAt(allParams, i);
+ SgShaderParamData *currentData = (SgShaderParamData*)rsGetElementAt(current->data, 0);
+#ifdef DEBUG_PARAMS
+ debugParam(current, currentData);
+#endif // DEBUG_PARAMS
+ updated = processParam(current, currentData, constantBuffer, camera, NULL) || updated;
+ }
+ }
+}
+
+static void processTextureParams(SgFragmentShader *shader) {
+ int numParams = 0;
+ if (rsIsObject(shader->shaderTextureParams)) {
+ numParams = rsAllocationGetDimX(shader->shaderTextureParams);
+ }
+ for (int i = 0; i < numParams; i ++) {
+ SgShaderParam *current = (SgShaderParam*)rsGetElementAt(shader->shaderTextureParams, i);
+ SgShaderParamData *currentData = (SgShaderParamData*)rsGetElementAt(current->data, 0);
+#ifdef DEBUG_PARAMS
+ debugParam(current, currentData);
+#endif // DEBUG_PARAMS
+ processParam(current, currentData, NULL, NULL, shader);
+ }
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs
new file mode 100644
index 0000000..d8d48b3
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs
@@ -0,0 +1,240 @@
+// Copyright (C) 2011-2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.scenegraph)
+
+#include "rs_graphics.rsh"
+#include "scenegraph_objects.rsh"
+
+rs_script gTransformScript;
+rs_script gCameraScript;
+rs_script gLightScript;
+rs_script gObjectParamsScript;
+rs_script gFragmentParamsScript;
+rs_script gVertexParamsScript;
+rs_script gCullScript;
+
+SgTransform *gRootNode;
+rs_allocation gCameras;
+rs_allocation gLights;
+rs_allocation gFragmentShaders;
+rs_allocation gVertexShaders;
+rs_allocation gRenderableObjects;
+
+rs_allocation gRenderPasses;
+
+// Temporary shaders
+rs_program_store gPFSBackground;
+
+uint32_t *gFrontToBack;
+static uint32_t gFrontToBackCount = 0;
+uint32_t *gBackToFront;
+static uint32_t gBackToFrontCount = 0;
+
+static SgCamera *gActiveCamera = NULL;
+
+static rs_allocation nullAlloc;
+
+// #define DEBUG_RENDERABLES
+static void draw(SgRenderable *obj) {
+#ifdef DEBUG_RENDERABLES
+ const SgTransform *objTransform = (const SgTransform *)rsGetElementAt(obj->transformMatrix, 0);
+ rsDebug("**** Drawing object with transform", obj);
+ printName(objTransform->name);
+ rsDebug("Model matrix: ", &objTransform->globalMat);
+ printName(obj->name);
+#endif //DEBUG_RENDERABLES
+
+ const SgRenderState *renderState = (const SgRenderState *)rsGetElementAt(obj->render_state, 0);
+ const SgVertexShader *pv = (const SgVertexShader *)rsGetElementAt(renderState->pv, 0);
+ const SgFragmentShader *pf = (const SgFragmentShader *)rsGetElementAt(renderState->pf, 0);
+
+ if (pv->objectConstIndex != -1) {
+ rsgBindConstant(pv->program, pv->objectConstIndex, obj->pv_const);
+ }
+ if (pf->objectConstIndex != -1) {
+ rsgBindConstant(pf->program, pf->objectConstIndex, obj->pf_const);
+ }
+
+ if (rsIsObject(renderState->ps)) {
+ rsgBindProgramStore(renderState->ps);
+ } else {
+ rsgBindProgramStore(gPFSBackground);
+ }
+
+ if (rsIsObject(renderState->pr)) {
+ rsgBindProgramRaster(renderState->pr);
+ } else {
+ rs_program_raster pr;
+ rsgBindProgramRaster(pr);
+ }
+
+ rsgBindProgramVertex(pv->program);
+ rsgBindProgramFragment(pf->program);
+
+ for (uint32_t i = 0; i < obj->pf_num_textures; i ++) {
+ const SgTexture *tex = rsGetElementAt(obj->pf_textures[i], 0);
+ rsgBindTexture(pf->program, i, tex->texture);
+ }
+
+ rsgDrawMesh(obj->mesh, obj->meshIndex);
+}
+
+static void sortToBucket(SgRenderable *obj) {
+ const SgRenderState *renderState = (const SgRenderState *)rsGetElementAt(obj->render_state, 0);
+ if (rsIsObject(renderState->ps)) {
+ bool isOpaque = false;
+ if (isOpaque) {
+ gFrontToBack[gFrontToBackCount++] = (uint32_t)obj;
+ } else {
+ gBackToFront[gBackToFrontCount++] = (uint32_t)obj;
+ }
+ } else {
+ gFrontToBack[gFrontToBackCount++] = (uint32_t)obj;
+ }
+}
+
+static void updateActiveCamera(rs_allocation cam) {
+ gActiveCamera = (SgCamera *)rsGetElementAt(cam, 0);
+}
+
+static void prepareCameras() {
+ // now compute all the camera matrices
+ if (rsIsObject(gCameras)) {
+ float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+ rsForEach(gCameraScript, gCameras, nullAlloc, &aspect, sizeof(aspect));
+ }
+}
+
+static void prepareLights() {
+ if (rsIsObject(gLights)) {
+ rsForEach(gLightScript, gLights, nullAlloc);
+ }
+}
+
+static void drawSorted() {
+ for (int i = 0; i < gFrontToBackCount; i ++) {
+ SgRenderable *current = (SgRenderable*)gFrontToBack[i];
+ draw(current);
+ }
+
+ for (int i = 0; i < gBackToFrontCount; i ++) {
+ SgRenderable *current = (SgRenderable*)gBackToFront[i];
+ draw(current);
+ }
+}
+
+static void drawAllObjects(rs_allocation allObj) {
+ if (!rsIsObject(allObj)) {
+ return;
+ }
+
+ rsForEach(gVertexParamsScript, nullAlloc, gVertexShaders,
+ gActiveCamera, sizeof(gActiveCamera));
+ rsForEach(gFragmentParamsScript, nullAlloc, gFragmentShaders,
+ gActiveCamera, sizeof(gActiveCamera));
+
+ // Run the params and cull script
+ rsForEach(gCullScript, nullAlloc, allObj, gActiveCamera, sizeof(gActiveCamera));
+ rsForEach(gObjectParamsScript, nullAlloc, allObj, gActiveCamera, sizeof(gActiveCamera));
+
+ int numRenderables = rsAllocationGetDimX(allObj);
+ for (int i = 0; i < numRenderables; i ++) {
+ rs_allocation *drawAlloc = (rs_allocation*)rsGetElementAt(allObj, i);
+ SgRenderable *current = (SgRenderable*)rsGetElementAt(*drawAlloc, 0);
+ if (current->isVisible) {
+ sortToBucket(current);
+ }
+ }
+ drawSorted();
+}
+
+int root(void) {
+#ifdef DEBUG_RENDERABLES
+ rsDebug("=============================================================================", 0);
+#endif // DEBUG_RENDERABLES
+
+ // first step is to update the transform hierachy
+ if (gRootNode && rsIsObject(gRootNode->children)) {
+ rsForEach(gTransformScript, gRootNode->children, nullAlloc, 0, 0);
+ }
+
+ prepareCameras();
+ prepareLights();
+
+ if (rsIsObject(gRenderPasses)) {
+ rsgClearDepth(1.0f);
+ int numPasses = rsAllocationGetDimX(gRenderPasses);
+ for (uint i = 0; i < numPasses; i ++) {
+ gFrontToBackCount = 0;
+ gBackToFrontCount = 0;
+ SgRenderPass *pass = (SgRenderPass*)rsGetElementAt(gRenderPasses, i);
+ if (rsIsObject(pass->color_target)) {
+ rsgBindColorTarget(pass->color_target, 0);
+ }
+ if (rsIsObject(pass->depth_target)) {
+ rsgBindDepthTarget(pass->depth_target);
+ }
+ if (!rsIsObject(pass->color_target) &&
+ !rsIsObject(pass->depth_target)) {
+ rsgClearAllRenderTargets();
+ }
+ updateActiveCamera(pass->camera);
+ if (pass->should_clear_color) {
+ rsgClearColor(pass->clear_color.x, pass->clear_color.y,
+ pass->clear_color.z, pass->clear_color.w);
+ }
+ if (pass->should_clear_depth) {
+ rsgClearDepth(pass->clear_depth);
+ }
+ drawAllObjects(pass->objects);
+ }
+ } else {
+ gFrontToBackCount = 0;
+ gBackToFrontCount = 0;
+ rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+ rsgClearDepth(1.0f);
+
+ if (rsIsObject(gCameras)) {
+ rs_allocation *camAlloc = (rs_allocation*)rsGetElementAt(gCameras, 0);
+ updateActiveCamera(*camAlloc);
+ }
+ drawAllObjects(gRenderableObjects);
+ }
+ return 10;
+}
+
+// Search through sorted and culled objects
+void pick(int screenX, int screenY) {
+ float3 pnt, vec;
+ getCameraRay(gActiveCamera, screenX, screenY, &pnt, &vec);
+
+ for (int i = 0; i < gFrontToBackCount; i ++) {
+ SgRenderable *current = (SgRenderable*)gFrontToBack[i];
+ bool isPicked = intersect(current, pnt, vec);
+ if (isPicked) {
+ current->cullType = CULL_ALWAYS;
+ }
+ }
+
+ for (int i = 0; i < gBackToFrontCount; i ++) {
+ SgRenderable *current = (SgRenderable*)gBackToFront[i];
+ bool isPicked = intersect(current, pnt, vec);
+ if (isPicked) {
+ current->cullType = CULL_ALWAYS;
+ }
+ }
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/scenegraph_objects.rsh b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/scenegraph_objects.rsh
new file mode 100644
index 0000000..bdca3ab
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/scenegraph_objects.rsh
@@ -0,0 +1,323 @@
+// Copyright (C) 2011-2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.scenegraph)
+
+#ifndef _TRANSFORM_DEF_
+#define _TRANSFORM_DEF_
+
+#include "rs_graphics.rsh"
+
+#define TRANSFORM_NONE 0
+#define TRANSFORM_TRANSLATE 1
+#define TRANSFORM_ROTATE 2
+#define TRANSFORM_SCALE 3
+
+#define CULL_FRUSTUM 0
+#define CULL_ALWAYS 2
+
+#define LIGHT_POINT 0
+#define LIGHT_DIRECTIONAL 1
+
+// Shader params that involve only data
+#define SHADER_PARAM_DATA_ONLY 10000
+#define SHADER_PARAM_FLOAT4_DATA 10001
+#define SHADER_PARAM_TRANSFORM_DATA 10002
+#define SHADER_PARAM_TRANSFORM_MODEL 10003
+
+// Shader params that involve camera
+#define SHADER_PARAM_CAMERA 1000
+#define SHADER_PARAM_FLOAT4_CAMERA_POS 1001
+#define SHADER_PARAM_FLOAT4_CAMERA_DIR 1002
+#define SHADER_PARAM_TRANSFORM_VIEW 1003
+#define SHADER_PARAM_TRANSFORM_PROJ 1004
+#define SHADER_PARAM_TRANSFORM_VIEW_PROJ 1005
+#define SHADER_PARAM_TRANSFORM_MODEL_VIEW 1006
+#define SHADER_PARAM_TRANSFORM_MODEL_VIEW_PROJ 1007
+
+// Shader Params that only involve lights
+#define SHADER_PARAM_LIGHT 100
+#define SHADER_PARAM_FLOAT4_LIGHT_COLOR 103
+#define SHADER_PARAM_FLOAT4_LIGHT_POS 104
+#define SHADER_PARAM_FLOAT4_LIGHT_DIR 105
+
+#define SHADER_PARAM_TEXTURE 10
+
+#define TEXTURE_NONE 0
+#define TEXTURE_2D 1
+#define TEXTURE_CUBE 2
+#define TEXTURE_RENDER_TARGET 3
+
+typedef struct TransformComponent_s {
+ float4 value;
+ int type;
+ rs_allocation name;
+} SgTransformComponent;
+
+typedef struct __attribute__((packed, aligned(4))) SgTransform {
+ rs_matrix4x4 globalMat;
+ rs_matrix4x4 localMat;
+
+ rs_allocation components;
+ int isDirty;
+
+ rs_allocation children;
+ rs_allocation name;
+
+ // Used to check whether transform params need to be updated
+ uint32_t timestamp;
+} SgTransform;
+
+typedef struct VertexShader_s {
+ rs_program_vertex program;
+ // Buffer with vertex constant data
+ rs_allocation shaderConst;
+ // ShaderParam's that populate data
+ rs_allocation shaderConstParams;
+ // location of the per object constants on the buffer
+ int objectConstIndex;
+} SgVertexShader;
+
+typedef struct FragmentShader_s {
+ rs_program_fragment program;
+ // Buffer with vertex constant data
+ rs_allocation shaderConst;
+ // ShaderParam's that populate data
+ rs_allocation shaderConstParams;
+ // ShaderParam's that set textures
+ rs_allocation shaderTextureParams;
+ // location of the per object constants on the buffer
+ int objectConstIndex;
+} SgFragmentShader;
+
+typedef struct RenderState_s {
+ rs_allocation pv; // VertexShader struct
+ rs_allocation pf; // FragmentShader struct
+ rs_program_store ps;
+ rs_program_raster pr;
+} SgRenderState;
+
+typedef struct Renderable_s {
+ rs_allocation render_state;
+ // Buffer with vertex constant data
+ rs_allocation pv_const;
+ // ShaderParam's that populate data
+ rs_allocation pv_constParams;
+ // Buffer with fragment constant data
+ rs_allocation pf_const;
+ // ShaderParam's that populate data
+ rs_allocation pf_constParams;
+ rs_allocation pf_textures[8];
+ int pf_num_textures;
+ rs_mesh mesh;
+ int meshIndex;
+ rs_allocation transformMatrix;
+ rs_allocation name;
+ float4 boundingSphere;
+ float4 worldBoundingSphere;
+ int bVolInitialized;
+ int cullType; // specifies whether to frustum cull
+ int isVisible;
+} SgRenderable;
+
+typedef struct RenderPass_s {
+ rs_allocation color_target;
+ rs_allocation depth_target;
+ rs_allocation camera;
+ rs_allocation objects;
+
+ float4 clear_color;
+ float clear_depth;
+ bool should_clear_color;
+ bool should_clear_depth;
+} SgRenderPass;
+
+typedef struct Camera_s {
+ rs_matrix4x4 proj;
+ rs_matrix4x4 view;
+ rs_matrix4x4 viewProj;
+ float4 position;
+ float near;
+ float far;
+ float horizontalFOV;
+ float aspect;
+ rs_allocation name;
+ rs_allocation transformMatrix;
+ float4 frustumPlanes[6];
+
+ int isDirty;
+ // Timestamp of the camera itself to signal params if anything changes
+ uint32_t timestamp;
+ // Timestamp of our transform
+ uint32_t transformTimestamp;
+} SgCamera;
+
+typedef struct Light_s {
+ float4 position;
+ float4 color;
+ float intensity;
+ int type;
+ rs_allocation name;
+ rs_allocation transformMatrix;
+} SgLight;
+
+// This represents the shader parameter data needed to set a float or transform data
+typedef struct ShaderParamData_s {
+ int type;
+ float4 float_value;
+ uint32_t timestamp;
+ rs_allocation paramName;
+ rs_allocation camera;
+ rs_allocation light;
+ rs_allocation transform;
+ rs_allocation texture;
+} SgShaderParamData;
+
+// This represents a shader parameter that knows how to update itself for a given
+// renderable or shader and contains a timestamp for the last time this buffer was updated
+typedef struct ShaderParam_s {
+ // Used to check whether transform params need to be updated
+ uint32_t transformTimestamp;
+ // Used to check whether data params need to be updated
+ // These are used when somebody set the matrix of float value directly in java
+ uint32_t dataTimestamp;
+ // Specifies where in the constant buffer data gets written to
+ int bufferOffset;
+ // An instance of SgShaderParamData that could be shared by multiple objects
+ rs_allocation data;
+ // How many components of the vector we need to write
+ int float_vecSize;
+} SgShaderParam;
+
+// This represents a texture object
+typedef struct Texture_s {
+ uint32_t type;
+ rs_allocation texture;
+} SgTexture;
+
+static void printName(rs_allocation name) {
+ if (!rsIsObject(name)) {
+ rsDebug("no name", 0);
+ return;
+ }
+
+ rsDebug((const char*)rsGetElementAt(name, 0), 0);
+}
+
+static void printCameraInfo(const SgCamera *cam) {
+ rsDebug("***** Camera information. ptr:", cam);
+ printName(cam->name);
+ const SgTransform *camTransform = (const SgTransform *)rsGetElementAt(cam->transformMatrix, 0);
+ rsDebug("Transform name:", camTransform);
+ printName(camTransform->name);
+
+ rsDebug("Aspect: ", cam->aspect);
+ rsDebug("Near: ", cam->near);
+ rsDebug("Far: ", cam->far);
+ rsDebug("Fov: ", cam->horizontalFOV);
+ rsDebug("Position: ", cam->position);
+ rsDebug("Proj: ", &cam->proj);
+ rsDebug("View: ", &cam->view);
+}
+
+static void printLightInfo(const SgLight *light) {
+ rsDebug("***** Light information. ptr:", light);
+ printName(light->name);
+ const SgTransform *lTransform = (const SgTransform *)rsGetElementAt(light->transformMatrix, 0);
+ rsDebug("Transform name:", lTransform);
+ printName(lTransform->name);
+
+ rsDebug("Position: ", light->position);
+ rsDebug("Color : ", light->color);
+ rsDebug("Intensity: ", light->intensity);
+ rsDebug("Type: ", light->type);
+}
+
+static void getCameraRay(const SgCamera *cam, int screenX, int screenY, float3 *pnt, float3 *vec) {
+ rsDebug("=================================", screenX);
+ rsDebug("Point X", screenX);
+ rsDebug("Point Y", screenY);
+
+ rs_matrix4x4 mvpInv;
+ rsMatrixLoad(&mvpInv, &cam->viewProj);
+ rsMatrixInverse(&mvpInv);
+
+ float width = (float)rsgGetWidth();
+ float height = (float)rsgGetHeight();
+
+ float4 pos = {(float)screenX, height - (float)screenY, 0.0f, 1.0f};
+
+ pos.x /= width;
+ pos.y /= height;
+
+ rsDebug("Pre Norm X", pos.x);
+ rsDebug("Pre Norm Y", pos.y);
+
+ pos.xy = pos.xy * 2.0f - 1.0f;
+
+ rsDebug("Norm X", pos.x);
+ rsDebug("Norm Y", pos.y);
+
+ pos = rsMatrixMultiply(&mvpInv, pos);
+ float oneOverW = 1.0f / pos.w;
+ pos.xyz *= oneOverW;
+
+ rsDebug("World X", pos.x);
+ rsDebug("World Y", pos.y);
+ rsDebug("World Z", pos.z);
+
+ rsDebug("Cam X", cam->position.x);
+ rsDebug("Cam Y", cam->position.y);
+ rsDebug("Cam Z", cam->position.z);
+
+ *vec = normalize(pos.xyz - cam->position.xyz);
+ rsDebug("Vec X", vec->x);
+ rsDebug("Vec Y", vec->y);
+ rsDebug("Vec Z", vec->z);
+ *pnt = cam->position.xyz;
+}
+
+static bool intersect(const SgRenderable *obj, float3 pnt, float3 vec) {
+ // Solving for t^2 + Bt + C = 0
+ float3 originMinusCenter = pnt - obj->worldBoundingSphere.xyz;
+ float B = dot(originMinusCenter, vec) * 2.0f;
+ float C = dot(originMinusCenter, originMinusCenter) -
+ obj->worldBoundingSphere.w * obj->worldBoundingSphere.w;
+
+ float discriminant = B * B - 4.0f * C;
+ if (discriminant < 0.0f) {
+ return false;
+ }
+ discriminant = sqrt(discriminant);
+
+ float t0 = (-B - discriminant) * 0.5f;
+ float t1 = (-B + discriminant) * 0.5f;
+
+ if (t0 > t1) {
+ float temp = t0;
+ t0 = t1;
+ t1 = temp;
+ }
+
+ // The sphere is behind us
+ if (t1 < 0.0f) {
+ return false;
+ }
+ return true;
+}
+
+
+#endif // _TRANSFORM_DEF_
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/transform.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/transform.rs
new file mode 100644
index 0000000..941b5a8
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/transform.rs
@@ -0,0 +1,127 @@
+// 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.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.modelviewer)
+
+#include "scenegraph_objects.rsh"
+
+rs_script gTransformScript;
+
+typedef struct {
+ int changed;
+ rs_matrix4x4 *mat;
+} ParentData;
+
+//#define DEBUG_TRANSFORMS
+static void debugTransform(SgTransform *data, const ParentData *parent) {
+ rsDebug("****** <Transform> ******", (int)data);
+ printName(data->name);
+ rsDebug("isDirty", data->isDirty);
+ rsDebug("parent", (int)parent);
+ rsDebug("child ", rsIsObject(data->children));
+
+ // Refresh matrices if dirty
+ if (data->isDirty && rsIsObject(data->components)) {
+ uint32_t numComponenets = rsAllocationGetDimX(data->components);
+ for (int i = 0; i < numComponenets; i ++) {
+ const SgTransformComponent *comp = NULL;
+ comp = (const SgTransformComponent *)rsGetElementAt(data->components, i);
+
+ if (rsIsObject(comp->name)) {
+ rsDebug((const char*)rsGetElementAt(comp->name, 0), comp->value);
+ rsDebug("Type", comp->type);
+ } else {
+ rsDebug("no name", comp->value);
+ rsDebug("Type", comp->type);
+ }
+ }
+ }
+
+ rsDebug("timestamp", data->timestamp);
+ rsDebug("****** </Transform> ******", (int)data);
+}
+
+static void appendTransformation(int type, float4 data, rs_matrix4x4 *mat) {
+ rs_matrix4x4 temp;
+
+ switch (type) {
+ case TRANSFORM_TRANSLATE:
+ rsMatrixLoadTranslate(&temp, data.x, data.y, data.z);
+ break;
+ case TRANSFORM_ROTATE:
+ rsMatrixLoadRotate(&temp, data.w, data.x, data.y, data.z);
+ break;
+ case TRANSFORM_SCALE:
+ rsMatrixLoadScale(&temp, data.x, data.y, data.z);
+ break;
+ }
+ rsMatrixMultiply(mat, &temp);
+}
+
+void root(const rs_allocation *v_in, rs_allocation *v_out, const void *usrData) {
+
+ SgTransform *data = (SgTransform *)rsGetElementAt(*v_in, 0);
+ const ParentData *parent = (const ParentData *)usrData;
+
+#ifdef DEBUG_TRANSFORMS
+ debugTransform(data, parent);
+#endif //DEBUG_TRANSFORMS
+
+ rs_matrix4x4 *localMat = &data->localMat;
+ rs_matrix4x4 *globalMat = &data->globalMat;
+
+ // Refresh matrices if dirty
+ if (data->isDirty && rsIsObject(data->components)) {
+ bool resetLocal = false;
+ uint32_t numComponenets = rsAllocationGetDimX(data->components);
+ for (int i = 0; i < numComponenets; i ++) {
+ if (!resetLocal) {
+ // Reset our local matrix only for component transforms
+ rsMatrixLoadIdentity(localMat);
+ resetLocal = true;
+ }
+ const SgTransformComponent *comp = NULL;
+ comp = (const SgTransformComponent *)rsGetElementAt(data->components, i);
+ appendTransformation(comp->type, comp->value, localMat);
+ }
+ }
+
+ if (parent) {
+ data->isDirty = (parent->changed || data->isDirty) ? 1 : 0;
+ if (data->isDirty) {
+ rsMatrixLoad(globalMat, parent->mat);
+ rsMatrixMultiply(globalMat, localMat);
+ }
+ } else if (data->isDirty) {
+ rsMatrixLoad(globalMat, localMat);
+ }
+
+ ParentData toChild;
+ toChild.changed = 0;
+ toChild.mat = globalMat;
+
+ if (data->isDirty) {
+ toChild.changed = 1;
+ data->timestamp ++;
+ }
+
+ if (rsIsObject(data->children)) {
+ rs_allocation nullAlloc;
+ rsForEach(gTransformScript, data->children, nullAlloc, &toChild, sizeof(toChild));
+ }
+
+ data->isDirty = 0;
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/vertex_params.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/vertex_params.rs
new file mode 100644
index 0000000..88955a8
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/vertex_params.rs
@@ -0,0 +1,29 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.scenegraph)
+
+#include "scenegraph_objects.rsh"
+
+//#define DEBUG_PARAMS
+
+#include "params.rsh"
+
+void root(rs_allocation *v_out, const void *usrData) {
+ SgVertexShader *shader = (SgVertexShader *)rsGetElementAt(*v_out, 0);
+ const SgCamera *camera = (const SgCamera*)usrData;
+ processAllParams(shader->shaderConst, shader->shaderConstParams, camera);
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/FileSelector.java b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/FileSelector.java
new file mode 100644
index 0000000..420e133
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/FileSelector.java
@@ -0,0 +1,110 @@
+/*
+ * 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.testapp;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.ArrayList;
+import java.util.List;
+
+import android.app.ListActivity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+/**
+ * A list view where the last item the user clicked is placed in
+ * the "activated" state, causing its background to highlight.
+ */
+public class FileSelector extends ListActivity {
+
+ File[] mCurrentSubList;
+ File mCurrentFile;
+
+ class DAEFilter implements FileFilter {
+ public boolean accept(File file) {
+ if (file.isDirectory()) {
+ return true;
+ }
+ return file.getName().endsWith(".dae");
+ }
+ }
+
+ private void populateList(File file) {
+
+ mCurrentFile = file;
+ setTitle(mCurrentFile.getAbsolutePath() + "/*.dae");
+ List<String> names = new ArrayList<String>();
+ names.add("..");
+
+ mCurrentSubList = mCurrentFile.listFiles(new DAEFilter());
+
+ if (mCurrentSubList != null) {
+ for (int i = 0; i < mCurrentSubList.length; i ++) {
+ String fileName = mCurrentSubList[i].getName();
+ if (mCurrentSubList[i].isDirectory()) {
+ fileName = "/" + fileName;
+ }
+ names.add(fileName);
+ }
+ }
+
+ // Use the built-in layout for showing a list item with a single
+ // line of text whose background is changes when activated.
+ setListAdapter(new ArrayAdapter<String>(this,
+ android.R.layout.simple_list_item_activated_1, names));
+ getListView().setTextFilterEnabled(true);
+
+ // Tell the list view to show one checked/activated item at a time.
+ getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ populateList(new File("/sdcard/"));
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ if (position == 0) {
+ File parent = mCurrentFile.getParentFile();
+ if (parent == null) {
+ return;
+ }
+ populateList(parent);
+ return;
+ }
+
+ // the first thing in list is parent directory
+ File selectedFile = mCurrentSubList[position - 1];
+ if (selectedFile.isDirectory()) {
+ populateList(selectedFile);
+ return;
+ }
+
+ Intent resultIntent = new Intent();
+ resultIntent.setData(Uri.fromFile(selectedFile));
+ setResult(RESULT_OK, resultIntent);
+ finish();
+ }
+
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/FullscreenBlur.java b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/FullscreenBlur.java
new file mode 100644
index 0000000..28f916c
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/FullscreenBlur.java
@@ -0,0 +1,192 @@
+/*
+ * 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.testapp;
+
+import java.util.ArrayList;
+
+import com.android.scenegraph.*;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.AsyncTask;
+import android.renderscript.*;
+import android.renderscript.Allocation.MipmapControl;
+import android.renderscript.Element.Builder;
+import android.renderscript.Font.Style;
+import android.renderscript.Program.TextureType;
+import android.renderscript.ProgramStore.DepthFunc;
+import android.util.Log;
+
+class FullscreenBlur {
+
+ static TextureRenderTarget sRenderTargetBlur0Color;
+ static TextureRenderTarget sRenderTargetBlur0Depth;
+ static TextureRenderTarget sRenderTargetBlur1Color;
+ static TextureRenderTarget sRenderTargetBlur1Depth;
+ static TextureRenderTarget sRenderTargetBlur2Color;
+ static TextureRenderTarget sRenderTargetBlur2Depth;
+
+ static FragmentShader mPF_BlurH;
+ static FragmentShader mPF_BlurV;
+ static FragmentShader mPF_SelectColor;
+ static FragmentShader mPF_Texture;
+ static VertexShader mPV_Paint;
+ static VertexShader mPV_Blur;
+
+ static int targetWidth;
+ static int targetHeight;
+
+ // This is only used when full screen blur is enabled
+ // Basically, it's the offscreen render targets
+ static void createRenderTargets(RenderScriptGL rs, int w, int h) {
+ targetWidth = w/8;
+ targetHeight = h/8;
+ Type.Builder b = new Type.Builder(rs, Element.RGBA_8888(rs));
+ Type renderType = b.setX(targetWidth).setY(targetHeight).create();
+ int usage = Allocation.USAGE_GRAPHICS_TEXTURE | Allocation.USAGE_GRAPHICS_RENDER_TARGET;
+ sRenderTargetBlur0Color = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));
+ sRenderTargetBlur1Color = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));
+ sRenderTargetBlur2Color = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));
+
+ b = new Type.Builder(rs, Element.createPixel(rs, Element.DataType.UNSIGNED_16,
+ Element.DataKind.PIXEL_DEPTH));
+ renderType = b.setX(targetWidth).setY(targetHeight).create();
+ usage = Allocation.USAGE_GRAPHICS_RENDER_TARGET;
+ sRenderTargetBlur0Depth = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));
+ sRenderTargetBlur1Depth = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));
+ sRenderTargetBlur2Depth = new TextureRenderTarget(Allocation.createTyped(rs, renderType, usage));
+ }
+
+ static void addOffsets(Renderable quad, float advance) {
+ quad.appendSourceParams(new Float4Param("blurOffset0", - advance * 2.5f));
+ quad.appendSourceParams(new Float4Param("blurOffset1", - advance * 0.5f));
+ quad.appendSourceParams(new Float4Param("blurOffset2", advance * 1.5f));
+ quad.appendSourceParams(new Float4Param("blurOffset3", advance * 3.5f));
+ }
+
+ static RenderPass addPass(Scene scene, Camera cam, TextureRenderTarget color, TextureRenderTarget depth) {
+ RenderPass pass = new RenderPass();
+ pass.setColorTarget(color);
+ pass.setDepthTarget(depth);
+ pass.setShouldClearColor(false);
+ pass.setShouldClearDepth(false);
+ pass.setCamera(cam);
+ scene.appendRenderPass(pass);
+ return pass;
+ }
+
+ static void addBlurPasses(Scene scene, RenderScriptGL rs, Camera cam) {
+ SceneManager sceneManager = SceneManager.getInstance();
+ ArrayList<RenderableBase> allDraw = scene.getRenderables();
+ int numDraw = allDraw.size();
+
+ ProgramRaster cullNone = ProgramRaster.CULL_NONE(rs);
+ ProgramStore blendAdd = SceneManager.BLEND_ADD_DEPTH_NONE(rs);
+ ProgramStore blendNone = ProgramStore.BLEND_NONE_DEPTH_NONE(rs);
+
+ RenderState drawTex = new RenderState(mPV_Blur, mPF_Texture, blendAdd, cullNone);
+ RenderState selectCol = new RenderState(mPV_Blur, mPF_SelectColor, blendNone, cullNone);
+ RenderState hBlur = new RenderState(mPV_Blur, mPF_BlurH, blendNone, cullNone);
+ RenderState vBlur = new RenderState(mPV_Blur, mPF_BlurV, blendNone, cullNone);
+
+ // Renders the scene off screen
+ RenderPass blurSourcePass = addPass(scene, cam,
+ sRenderTargetBlur0Color,
+ sRenderTargetBlur0Depth);
+ blurSourcePass.setClearColor(new Float4(1.0f, 1.0f, 1.0f, 1.0f));
+ blurSourcePass.setShouldClearColor(true);
+ blurSourcePass.setClearDepth(1.0f);
+ blurSourcePass.setShouldClearDepth(true);
+ for (int i = 0; i < numDraw; i ++) {
+ blurSourcePass.appendRenderable((Renderable)allDraw.get(i));
+ }
+
+ // Pass for selecting bright colors
+ RenderPass selectColorPass = addPass(scene, cam,
+ sRenderTargetBlur2Color,
+ sRenderTargetBlur2Depth);
+ Renderable quad = sceneManager.getRenderableQuad("ScreenAlignedQuadS", selectCol);
+ quad.appendSourceParams(new TextureParam("color", sRenderTargetBlur0Color));
+ selectColorPass.appendRenderable(quad);
+
+ // Horizontal blur
+ RenderPass horizontalBlurPass = addPass(scene, cam,
+ sRenderTargetBlur1Color,
+ sRenderTargetBlur1Depth);
+ quad = sceneManager.getRenderableQuad("ScreenAlignedQuadH", hBlur);
+ quad.appendSourceParams(new TextureParam("color", sRenderTargetBlur2Color));
+ addOffsets(quad, 1.0f / (float)targetWidth);
+ horizontalBlurPass.appendRenderable(quad);
+
+ // Vertical Blur
+ RenderPass verticalBlurPass = addPass(scene, cam,
+ sRenderTargetBlur2Color,
+ sRenderTargetBlur2Depth);
+ quad = sceneManager.getRenderableQuad("ScreenAlignedQuadV", vBlur);
+ quad.appendSourceParams(new TextureParam("color", sRenderTargetBlur1Color));
+ addOffsets(quad, 1.0f / (float)targetHeight);
+ verticalBlurPass.appendRenderable(quad);
+ }
+
+ // Additively renders the blurred colors on top of the scene
+ static void addCompositePass(Scene scene, RenderScriptGL rs, Camera cam) {
+ SceneManager sceneManager = SceneManager.getInstance();
+ RenderState drawTex = new RenderState(mPV_Blur, mPF_Texture,
+ SceneManager.BLEND_ADD_DEPTH_NONE(rs),
+ ProgramRaster.CULL_NONE(rs));
+
+ RenderPass compositePass = addPass(scene, cam, null, null);
+ Renderable quad = sceneManager.getRenderableQuad("ScreenAlignedQuadComposite", drawTex);
+ quad.appendSourceParams(new TextureParam("color", sRenderTargetBlur2Color));
+ compositePass.appendRenderable(quad);
+ }
+
+ static private FragmentShader getShader(Resources res, RenderScriptGL rs,
+ int resID, Type constants) {
+ FragmentShader.Builder fb = new FragmentShader.Builder(rs);
+ fb.setShader(res, resID);
+ fb.addTexture(TextureType.TEXTURE_2D, "color");
+ if (constants != null) {
+ fb.setObjectConst(constants);
+ }
+ FragmentShader prog = fb.create();
+ prog.getProgram().bindSampler(Sampler.CLAMP_LINEAR(rs), 0);
+ return prog;
+ }
+
+ static void initShaders(Resources res, RenderScriptGL rs) {
+ ScriptField_BlurOffsets blurConst = new ScriptField_BlurOffsets(rs, 1);
+ VertexShader.Builder vb = new VertexShader.Builder(rs);
+ vb.addInput(ScriptField_VertexShaderInputs.createElement(rs));
+ vb.setShader(res, R.raw.blur_vertex);
+ mPV_Blur = vb.create();
+
+ mPF_Texture = getShader(res, rs, R.raw.texture, null);
+ mPF_Texture.getProgram().bindSampler(Sampler.WRAP_LINEAR_MIP_LINEAR(rs), 0);
+ mPF_BlurH = getShader(res, rs, R.raw.blur_h, blurConst.getAllocation().getType());
+ mPF_BlurV = getShader(res, rs, R.raw.blur_v, blurConst.getAllocation().getType());
+ mPF_SelectColor = getShader(res, rs, R.raw.select_color, null);
+ }
+
+}
+
+
+
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestApp.java b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestApp.java
new file mode 100644
index 0000000..385a7ab
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestApp.java
@@ -0,0 +1,115 @@
+/*
+ * 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.testapp;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings.System;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.ListView;
+import android.view.MenuInflater;
+import android.view.Window;
+import android.net.Uri;
+
+import java.lang.Runtime;
+
+public class TestApp extends Activity {
+
+ private TestAppView mView;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ // Create our Preview view and set it as the content of our
+ // Activity
+ mView = new TestAppView(this);
+ setContentView(mView);
+ }
+
+ @Override
+ protected void onResume() {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mView.resume();
+ }
+
+ @Override
+ protected void onPause() {
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mView.pause();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.loader_menu, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle item selection
+ switch (item.getItemId()) {
+ case R.id.load_model:
+ loadModel();
+ return true;
+ case R.id.use_blur:
+ mView.mRender.toggleBlur();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ private static final int FIND_DAE_MODEL = 10;
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (resultCode == RESULT_OK) {
+ if (requestCode == FIND_DAE_MODEL) {
+ Uri selectedImageUri = data.getData();
+ Log.e("Selected Path: ", selectedImageUri.getPath());
+ mView.mRender.loadModel(selectedImageUri.getPath());
+ }
+ }
+ }
+
+ public void loadModel() {
+ Intent intent = new Intent();
+ intent.setAction(Intent.ACTION_PICK);
+ intent.setClassName("com.android.testapp",
+ "com.android.testapp.FileSelector");
+ startActivityForResult(intent, FIND_DAE_MODEL);
+ }
+
+}
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppLoadingScreen.java b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppLoadingScreen.java
new file mode 100644
index 0000000..5bd8f0b
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppLoadingScreen.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.testapp;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+import com.android.scenegraph.SceneManager;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.AsyncTask;
+import android.renderscript.*;
+import android.renderscript.Allocation.MipmapControl;
+import android.renderscript.Element.Builder;
+import android.renderscript.Font.Style;
+import android.renderscript.Program.TextureType;
+import android.renderscript.ProgramStore.DepthFunc;
+import android.util.Log;
+
+// This is where the scenegraph and the rendered objects are initialized and used
+public class TestAppLoadingScreen {
+
+ private static String TAG = "TestAppLoadingScreen";
+
+ private Resources mRes;
+ private RenderScriptGL mRS;
+ private ScriptC_test_app mScript;
+
+ public TestAppLoadingScreen(RenderScriptGL rs, Resources res) {
+ mRS = rs;
+ mRes = res;
+ // Shows the loading screen with some text
+ renderLoading();
+ // Adds a little 3D bugdroid model to the laoding screen asynchronously.
+ new LoadingScreenLoaderTask().execute();
+ }
+
+ public void showLoadingScreen(boolean show) {
+ if (show) {
+ mRS.bindRootScript(mScript);
+ } else {
+ mRS.bindRootScript(SceneManager.getInstance().getRenderLoop());
+ }
+ }
+
+ // The loading screen has some elements that shouldn't be loaded on the UI thread
+ private class LoadingScreenLoaderTask extends AsyncTask<String, Void, Boolean> {
+ Allocation robotTex;
+ Mesh robotMesh;
+ protected Boolean doInBackground(String... names) {
+ long start = System.currentTimeMillis();
+ robotTex = Allocation.createFromBitmapResource(mRS, mRes, R.drawable.robot,
+ MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+ Allocation.USAGE_GRAPHICS_TEXTURE);
+
+ FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.robot);
+ FileA3D.IndexEntry entry = model.getIndexEntry(0);
+ if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) {
+ robotMesh = entry.getMesh();
+ }
+
+ mScript.set_gPFSBackground(ProgramStore.BLEND_NONE_DEPTH_TEST(mRS));
+
+ ProgramFragmentFixedFunction.Builder b = new ProgramFragmentFixedFunction.Builder(mRS);
+ b.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
+ ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
+ ProgramFragment pfDefault = b.create();
+ pfDefault.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0);
+ mScript.set_gPFBackground(pfDefault);
+
+ ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
+ ProgramVertexFixedFunction pvDefault = pvb.create();
+ ProgramVertexFixedFunction.Constants va = new ProgramVertexFixedFunction.Constants(mRS);
+ ((ProgramVertexFixedFunction)pvDefault).bindConstants(va);
+ mScript.set_gPVBackground(pvDefault);
+
+ long end = System.currentTimeMillis();
+ Log.v("TIMER", "Loading load time: " + (end - start));
+ return new Boolean(true);
+ }
+
+ protected void onPostExecute(Boolean result) {
+ mScript.set_gRobotTex(robotTex);
+ mScript.set_gRobotMesh(robotMesh);
+ }
+ }
+
+ // Creates a simple script to show a loding screen until everything is initialized
+ // Could also be used to do some custom renderscript work before handing things over
+ // to the scenegraph
+ void renderLoading() {
+ mScript = new ScriptC_test_app(mRS, mRes, R.raw.test_app);
+ mRS.bindRootScript(mScript);
+ }
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppRS.java b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppRS.java
new file mode 100644
index 0000000..7bf7812
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppRS.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2011-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.testapp;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+import com.android.scenegraph.*;
+import com.android.scenegraph.SceneManager.SceneLoadedCallback;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.AsyncTask;
+import android.renderscript.*;
+import android.renderscript.Program.TextureType;
+import android.util.Log;
+
+// This is where the scenegraph and the rendered objects are initialized and used
+public class TestAppRS {
+
+ private static String modelName = "orientation_test.dae";
+ private static String TAG = "TestAppRS";
+ private static String mFilePath = "";
+
+ int mWidth;
+ int mHeight;
+
+ boolean mUseBlur;
+
+ TestAppLoadingScreen mLoadingScreen;
+
+ // Used to asynchronously load scene elements like meshes and transform hierarchies
+ SceneLoadedCallback mLoadedCallback = new SceneLoadedCallback() {
+ public void run() {
+ prepareToRender(mLoadedScene);
+ }
+ };
+
+ // Top level class that initializes all the elements needed to use the scene graph
+ SceneManager mSceneManager;
+
+ // Used to move the camera around in the 3D world
+ TouchHandler mTouchHandler;
+
+ private Resources mRes;
+ private RenderScriptGL mRS;
+
+ // Shaders
+ private FragmentShader mPaintF;
+ private FragmentShader mLightsF;
+ private FragmentShader mAluminumF;
+ private FragmentShader mPlasticF;
+ private FragmentShader mDiffuseF;
+ private FragmentShader mTextureF;
+ private VertexShader mGenericV;
+
+ Scene mActiveScene;
+
+ // This is a part of the test app, it's used to tests multiple render passes and is toggled
+ // on and off in the menu, off by default
+ void toggleBlur() {
+ mUseBlur = !mUseBlur;
+
+ mActiveScene.clearRenderPasses();
+ initRenderPasses();
+ mActiveScene.initRenderPassRS(mRS, mSceneManager);
+
+ // This is just a hardcoded object in the scene that gets turned on and off for the demo
+ // to make things look a bit better. This could be deleted in the cleanup
+ Renderable plane = (Renderable)mActiveScene.getRenderableByName("pPlaneShape1");
+ if (plane != null) {
+ plane.setVisible(!mUseBlur);
+ }
+ }
+
+ public void init(RenderScriptGL rs, Resources res, int width, int height) {
+ mUseBlur = false;
+ mRS = rs;
+ mRes = res;
+ mWidth = width;
+ mHeight = height;
+
+ mTouchHandler = new TouchHandler();
+
+ mSceneManager = SceneManager.getInstance();
+ // Initializes all the RS specific scenegraph elements
+ mSceneManager.initRS(mRS, mRes, mWidth, mHeight);
+
+ mLoadingScreen = new TestAppLoadingScreen(mRS, mRes);
+
+ // Initi renderscript stuff specific to the app. This will need to be abstracted out later.
+ FullscreenBlur.createRenderTargets(mRS, mWidth, mHeight);
+ initPaintShaders();
+
+ // Load a scene to render
+ mSceneManager.loadModel(mFilePath + modelName, mLoadedCallback);
+ }
+
+ // When a new model file is selected from the UI, this function gets called to init everything
+ void loadModel(String path) {
+ mLoadingScreen.showLoadingScreen(true);
+ mActiveScene.destroyRS();
+ mSceneManager.loadModel(path, mLoadedCallback);
+ }
+
+ public void onActionDown(float x, float y) {
+ mTouchHandler.onActionDown(x, y);
+ }
+
+ public void onActionScale(float scale) {
+ mTouchHandler.onActionScale(scale);
+ }
+
+ public void onActionMove(float x, float y) {
+ mTouchHandler.onActionMove(x, y);
+ }
+
+ FragmentShader createFromResource(int id, boolean addCubemap, Type constType) {
+ FragmentShader.Builder fb = new FragmentShader.Builder(mRS);
+ fb.setShaderConst(constType);
+ fb.setShader(mRes, id);
+ fb.addTexture(TextureType.TEXTURE_2D, "diffuse");
+ if (addCubemap) {
+ fb.addShaderTexture(TextureType.TEXTURE_CUBE, "reflection");
+ }
+ FragmentShader pf = fb.create();
+ pf.getProgram().bindSampler(Sampler.WRAP_LINEAR_MIP_LINEAR(mRS), 0);
+ if (addCubemap) {
+ pf.getProgram().bindSampler(Sampler.CLAMP_LINEAR_MIP_LINEAR(mRS), 1);
+ }
+ return pf;
+ }
+
+ private void initPaintShaders() {
+ ScriptField_ModelParams objConst = new ScriptField_ModelParams(mRS, 1);
+ ScriptField_ViewProjParams shaderConst = new ScriptField_ViewProjParams(mRS, 1);
+
+ VertexShader.Builder vb = new VertexShader.Builder(mRS);
+ vb.addInput(ScriptField_VertexShaderInputs.createElement(mRS));
+ vb.setShader(mRes, R.raw.shader2v);
+ vb.setObjectConst(objConst.getAllocation().getType());
+ vb.setShaderConst(shaderConst.getAllocation().getType());
+ mGenericV = vb.create();
+
+ ScriptField_CameraParams fsConst = new ScriptField_CameraParams(mRS, 1);
+ ScriptField_LightParams fsConst2 = new ScriptField_LightParams(mRS, 1);
+
+ mPaintF = createFromResource(R.raw.paintf, true, fsConst.getAllocation().getType());
+ // Assign a reflection map
+ TextureCube envCube = new TextureCube("sdcard/scenegraph/", "cube_env.png");
+ mPaintF.appendSourceParams(new TextureParam("reflection", envCube));
+
+ mAluminumF = createFromResource(R.raw.metal, true, fsConst.getAllocation().getType());
+ TextureCube diffCube = new TextureCube("sdcard/scenegraph/", "cube_spec.png");
+ mAluminumF.appendSourceParams(new TextureParam("reflection", diffCube));
+
+ mPlasticF = createFromResource(R.raw.plastic, false, fsConst.getAllocation().getType());
+ mDiffuseF = createFromResource(R.raw.diffuse, false, fsConst.getAllocation().getType());
+ mTextureF = createFromResource(R.raw.texture, false, fsConst.getAllocation().getType());
+
+ FragmentShader.Builder fb = new FragmentShader.Builder(mRS);
+ fb.setObjectConst(fsConst2.getAllocation().getType());
+ fb.setShader(mRes, R.raw.plastic_lights);
+ mLightsF = fb.create();
+
+ FullscreenBlur.initShaders(mRes, mRS);
+ }
+
+ void initRenderPasses() {
+ ArrayList<RenderableBase> allDraw = mActiveScene.getRenderables();
+ int numDraw = allDraw.size();
+
+ if (mUseBlur) {
+ FullscreenBlur.addBlurPasses(mActiveScene, mRS, mTouchHandler.getCamera());
+ }
+
+ RenderPass mainPass = new RenderPass();
+ mainPass.setClearColor(new Float4(1.0f, 1.0f, 1.0f, 1.0f));
+ mainPass.setShouldClearColor(true);
+ mainPass.setClearDepth(1.0f);
+ mainPass.setShouldClearDepth(true);
+ mainPass.setCamera(mTouchHandler.getCamera());
+ for (int i = 0; i < numDraw; i ++) {
+ mainPass.appendRenderable((Renderable)allDraw.get(i));
+ }
+ mActiveScene.appendRenderPass(mainPass);
+
+ if (mUseBlur) {
+ FullscreenBlur.addCompositePass(mActiveScene, mRS, mTouchHandler.getCamera());
+ }
+ }
+
+ private void addShadersToScene() {
+ mActiveScene.appendShader(mPaintF);
+ mActiveScene.appendShader(mLightsF);
+ mActiveScene.appendShader(mAluminumF);
+ mActiveScene.appendShader(mPlasticF);
+ mActiveScene.appendShader(mDiffuseF);
+ mActiveScene.appendShader(mTextureF);
+ mActiveScene.appendShader(mGenericV);
+ }
+
+ public void prepareToRender(Scene s) {
+ mSceneManager.setActiveScene(s);
+ mActiveScene = s;
+ mTouchHandler.init(mActiveScene);
+ addShadersToScene();
+ RenderState plastic = new RenderState(mGenericV, mPlasticF, null, null);
+ RenderState diffuse = new RenderState(mGenericV, mDiffuseF, null, null);
+ RenderState paint = new RenderState(mGenericV, mPaintF, null, null);
+ RenderState aluminum = new RenderState(mGenericV, mAluminumF, null, null);
+ RenderState lights = new RenderState(mGenericV, mLightsF, null, null);
+ RenderState glassTransp = new RenderState(mGenericV, mPaintF,
+ ProgramStore.BLEND_ALPHA_DEPTH_TEST(mRS), null);
+
+ initRenderPasses();
+
+ mActiveScene.assignRenderState(plastic);
+
+ mActiveScene.assignRenderStateToMaterial(diffuse, "lambert2$");
+
+ mActiveScene.assignRenderStateToMaterial(paint, "^Paint");
+ mActiveScene.assignRenderStateToMaterial(paint, "^Carbon");
+ mActiveScene.assignRenderStateToMaterial(paint, "^Glass");
+ mActiveScene.assignRenderStateToMaterial(paint, "^MainGlass");
+
+ mActiveScene.assignRenderStateToMaterial(aluminum, "^Metal");
+ mActiveScene.assignRenderStateToMaterial(aluminum, "^Brake");
+
+ mActiveScene.assignRenderStateToMaterial(glassTransp, "^GlassLight");
+
+ mActiveScene.assignRenderStateToMaterial(lights, "^LightBlinn");
+
+ Renderable plane = (Renderable)mActiveScene.getRenderableByName("pPlaneShape1");
+ if (plane != null) {
+ RenderState texState = new RenderState(mGenericV, mTextureF, null, null);
+ plane.setRenderState(texState);
+ plane.setVisible(!mUseBlur);
+ }
+
+ long start = System.currentTimeMillis();
+ mActiveScene.initRS();
+ long end = System.currentTimeMillis();
+ Log.v("TIMER", "Scene init time: " + (end - start));
+
+ mLoadingScreen.showLoadingScreen(false);
+ }
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppView.java b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppView.java
new file mode 100644
index 0000000..687f35b
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TestAppView.java
@@ -0,0 +1,152 @@
+/*
+ * 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.testapp;
+
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.concurrent.Semaphore;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+import android.renderscript.RenderScriptGL;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
+
+public class TestAppView extends RSSurfaceView {
+
+ public TestAppView(Context context) {
+ super(context);
+ mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
+ }
+
+ private RenderScriptGL mRS;
+ TestAppRS mRender;
+
+ private ScaleGestureDetector mScaleDetector;
+ private static final int INVALID_POINTER_ID = -1;
+ private int mActivePointerId = INVALID_POINTER_ID;
+
+ public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+ super.surfaceChanged(holder, format, w, h);
+ if (mRS == null) {
+ RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
+ sc.setDepth(16, 24);
+ mRS = createRenderScriptGL(sc);
+ mRS.setSurface(holder, w, h);
+ mRender = new TestAppRS();
+ mRender.init(mRS, getResources(), w, h);
+ }
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ if (mRS != null) {
+ mRender = null;
+ mRS = null;
+ destroyRenderScriptGL();
+ }
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event)
+ {
+ // break point at here
+ // this method doesn't work when 'extends View' include 'extends ScrollView'.
+ return super.onKeyDown(keyCode, event);
+ }
+
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ mScaleDetector.onTouchEvent(ev);
+
+ boolean ret = false;
+ float x = ev.getX();
+ float y = ev.getY();
+
+ final int action = ev.getAction();
+
+ switch (action & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_DOWN: {
+ mRender.onActionDown(x, y);
+ mActivePointerId = ev.getPointerId(0);
+ ret = true;
+ break;
+ }
+ case MotionEvent.ACTION_MOVE: {
+ if (!mScaleDetector.isInProgress()) {
+ mRender.onActionMove(x, y);
+ }
+ mRender.onActionDown(x, y);
+ ret = true;
+ break;
+ }
+
+ case MotionEvent.ACTION_UP: {
+ mActivePointerId = INVALID_POINTER_ID;
+ break;
+ }
+
+ case MotionEvent.ACTION_CANCEL: {
+ mActivePointerId = INVALID_POINTER_ID;
+ break;
+ }
+
+ case MotionEvent.ACTION_POINTER_UP: {
+ final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
+ >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ final int pointerId = ev.getPointerId(pointerIndex);
+ if (pointerId == mActivePointerId) {
+ // This was our active pointer going up. Choose a new
+ // active pointer and adjust accordingly.
+ final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
+ x = ev.getX(newPointerIndex);
+ y = ev.getY(newPointerIndex);
+ mRender.onActionDown(x, y);
+ mActivePointerId = ev.getPointerId(newPointerIndex);
+ }
+ break;
+ }
+ }
+
+ return ret;
+ }
+
+ private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
+ @Override
+ public boolean onScale(ScaleGestureDetector detector) {
+ mRender.onActionScale(detector.getScaleFactor());
+ return true;
+ }
+ }
+}
+
+
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TouchHandler.java b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TouchHandler.java
new file mode 100644
index 0000000..d8e48e8
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/TouchHandler.java
@@ -0,0 +1,114 @@
+/*
+ * 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.testapp;
+
+import android.util.Log;
+import android.renderscript.Float3;
+import com.android.scenegraph.*;
+import com.android.scenegraph.CompoundTransform.RotateComponent;
+import com.android.scenegraph.CompoundTransform.TranslateComponent;
+
+public class TouchHandler {
+ private static String TAG = "TouchHandler";
+
+ float mLastX;
+ float mLastY;
+
+ float mRotateXValue;
+ float mRotateYValue;
+ Float3 mDistValue;
+ Float3 mPosValue;
+
+ CompoundTransform mCameraRig;
+ RotateComponent mRotateX;
+ RotateComponent mRotateY;
+ TranslateComponent mDist;
+ TranslateComponent mPosition;
+ Camera mCamera;
+
+ public void init(Scene scene) {
+ // Some initial values for camera position
+ mRotateXValue = -20;
+ mRotateYValue = 45;
+ mDistValue = new Float3(0, 0, 45);
+ mPosValue = new Float3(0, 4, 0);
+
+ mRotateX = new RotateComponent("RotateX", new Float3(1, 0, 0), mRotateXValue);
+ mRotateY = new RotateComponent("RotateY", new Float3(0, 1, 0), mRotateYValue);
+ mDist = new TranslateComponent("Distance", mDistValue);
+ mPosition = new TranslateComponent("Distance", mPosValue);
+
+ // Make a camera transform we can manipulate
+ mCameraRig = new CompoundTransform();
+ mCameraRig.setName("CameraRig");
+ mCameraRig.addComponent(mPosition);
+ mCameraRig.addComponent(mRotateY);
+ mCameraRig.addComponent(mRotateX);
+ mCameraRig.addComponent(mDist);
+ scene.appendTransform(mCameraRig);
+ mCamera = new Camera();
+ mCamera.setTransform(mCameraRig);
+ scene.appendCamera(mCamera);
+ }
+
+ public Camera getCamera() {
+ return mCamera;
+ }
+
+ public void onActionDown(float x, float y) {
+ mLastX = x;
+ mLastY = y;
+ }
+
+ public void onActionScale(float scale) {
+ if (mDist == null) {
+ return;
+ }
+ mDistValue.z *= 1.0f / scale;
+ mDistValue.z = Math.max(10.0f, Math.min(mDistValue.z, 150.0f));
+ mDist.setValue(mDistValue);
+ }
+
+ public void onActionMove(float x, float y) {
+ if (mRotateX == null) {
+ return;
+ }
+
+ float dx = mLastX - x;
+ float dy = mLastY - y;
+
+ if (Math.abs(dy) <= 2.0f) {
+ dy = 0.0f;
+ }
+ if (Math.abs(dx) <= 2.0f) {
+ dx = 0.0f;
+ }
+
+ mRotateYValue += dx * 0.25f;
+ mRotateYValue %= 360.0f;
+
+ mRotateXValue += dy * 0.25f;
+ mRotateXValue = Math.max(mRotateXValue , -80.0f);
+ mRotateXValue = Math.min(mRotateXValue , 0.0f);
+
+ mRotateX.setAngle(mRotateXValue);
+ mRotateY.setAngle(mRotateYValue);
+
+ mLastX = x;
+ mLastY = y;
+ }
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/test_app.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/test_app.rs
new file mode 100644
index 0000000..997a1a7
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/test_app.rs
@@ -0,0 +1,86 @@
+// 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.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.testapp)
+
+#include "rs_graphics.rsh"
+#include "test_app.rsh"
+
+// Making sure these get reflected
+FBlurOffsets *blurExport;
+VShaderInputs *iExport;
+FShaderParams *fConst;
+FShaderLightParams *fConts2;
+VSParams *vConst2;
+VObjectParams *vConst3;
+
+rs_program_vertex gPVBackground;
+rs_program_fragment gPFBackground;
+
+rs_allocation gRobotTex;
+rs_mesh gRobotMesh;
+
+rs_program_store gPFSBackground;
+
+float gRotate;
+
+void init() {
+ gRotate = 0.0f;
+}
+
+static int pos = 50;
+static float gRotateY = 120.0f;
+static float3 gLookAt = 0;
+static float gZoom = 50.0f;
+static void displayLoading() {
+ if (rsIsObject(gRobotTex) && rsIsObject(gRobotMesh)) {
+ rsgBindProgramVertex(gPVBackground);
+ rs_matrix4x4 proj;
+ float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+ rsMatrixLoadPerspective(&proj, 30.0f, aspect, 1.0f, 100.0f);
+ rsgProgramVertexLoadProjectionMatrix(&proj);
+
+ rsgBindProgramFragment(gPFBackground);
+ rsgBindProgramStore(gPFSBackground);
+ rsgBindTexture(gPFBackground, 0, gRobotTex);
+
+ rs_matrix4x4 matrix;
+ rsMatrixLoadIdentity(&matrix);
+ // Position our models on the screen
+ gRotateY += rsGetDt()*100;
+ rsMatrixTranslate(&matrix, 0, 0, -gZoom);
+ rsMatrixRotate(&matrix, 20.0f, 1.0f, 0.0f, 0.0f);
+ rsMatrixRotate(&matrix, gRotateY, 0.0f, 1.0f, 0.0f);
+ rsMatrixScale(&matrix, 0.2f, 0.2f, 0.2f);
+ rsgProgramVertexLoadModelMatrix(&matrix);
+ rsgDrawMesh(gRobotMesh);
+ }
+
+ uint width = rsgGetWidth();
+ uint height = rsgGetHeight();
+ int left = 0, right = 0, top = 0, bottom = 0;
+ const char* text = "Initializing...";
+ rsgMeasureText(text, &left, &right, &top, &bottom);
+ int centeredPos = width / 2 - (right - left) / 2;
+ rsgDrawText(text, centeredPos, height / 2 + height / 10);
+}
+
+int root(void) {
+ rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+ rsgClearDepth(1.0f);
+ displayLoading();
+ return 30;
+}
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/test_app.rsh b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/test_app.rsh
new file mode 100644
index 0000000..5fbcbb2
--- /dev/null
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/test_app.rsh
@@ -0,0 +1,52 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.testapp)
+
+// Helpers
+typedef struct ViewProjParams {
+ rs_matrix4x4 viewProj;
+} VSParams;
+
+typedef struct ModelParams {
+ rs_matrix4x4 model;
+} VObjectParams;
+
+typedef struct CameraParams {
+ float4 cameraPos;
+} FShaderParams;
+
+typedef struct LightParams {
+ float4 lightPos_0;
+ float4 lightColor_0;
+ float4 lightPos_1;
+ float4 lightColor_1;
+ float4 cameraPos;
+ float4 diffuse;
+} FShaderLightParams;
+
+typedef struct BlurOffsets {
+ float blurOffset0;
+ float blurOffset1;
+ float blurOffset2;
+ float blurOffset3;
+} FBlurOffsets;
+
+typedef struct VertexShaderInputs {
+ float4 position;
+ float3 normal;
+ float2 texture0;
+} VShaderInputs;
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
index 2293678..c7bd809 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
@@ -64,9 +64,15 @@
unitTests = new ArrayList<UnitTest>();
+ unitTests.add(new UT_mesh(this, mRes, mCtx));
+ unitTests.add(new UT_element(this, mRes, mCtx));
+ unitTests.add(new UT_sampler(this, mRes, mCtx));
+ unitTests.add(new UT_program_store(this, mRes, mCtx));
+ unitTests.add(new UT_program_raster(this, mRes, mCtx));
unitTests.add(new UT_primitives(this, mRes, mCtx));
unitTests.add(new UT_constant(this, mRes, mCtx));
unitTests.add(new UT_vector(this, mRes, mCtx));
+ unitTests.add(new UT_array_init(this, mRes, mCtx));
unitTests.add(new UT_rsdebug(this, mRes, mCtx));
unitTests.add(new UT_rstime(this, mRes, mCtx));
unitTests.add(new UT_rstypes(this, mRes, mCtx));
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_array_init.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_array_init.java
new file mode 100644
index 0000000..b98b753
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_array_init.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_array_init extends UnitTest {
+ private Resources mRes;
+
+ protected UT_array_init(RSTestCore rstc, Resources res, Context ctx) {
+ super(rstc, "Array Init", ctx);
+ mRes = res;
+ }
+
+ private void checkInit(ScriptC_array_init s) {
+ float[] fa = s.get_fa();
+ _RS_ASSERT("fa[0] == 1.0", fa[0] == 1.0);
+ _RS_ASSERT("fa[1] == 9.9999f", fa[1] == 9.9999f);
+ _RS_ASSERT("fa[2] == 0", fa[2] == 0);
+ _RS_ASSERT("fa[3] == 0", fa[3] == 0);
+ _RS_ASSERT("fa.length == 4", fa.length == 4);
+
+ double[] da = s.get_da();
+ _RS_ASSERT("da[0] == 7.0", da[0] == 7.0);
+ _RS_ASSERT("da[1] == 8.88888", da[1] == 8.88888);
+ _RS_ASSERT("da.length == 2", da.length == 2);
+
+ byte[] ca = s.get_ca();
+ _RS_ASSERT("ca[0] == 'a'", ca[0] == 'a');
+ _RS_ASSERT("ca[1] == 7", ca[1] == 7);
+ _RS_ASSERT("ca[2] == 'b'", ca[2] == 'b');
+ _RS_ASSERT("ca[3] == 'c'", ca[3] == 'c');
+ _RS_ASSERT("ca.length == 4", ca.length == 4);
+
+ short[] sa = s.get_sa();
+ _RS_ASSERT("sa[0] == 1", sa[0] == 1);
+ _RS_ASSERT("sa[1] == 1", sa[1] == 1);
+ _RS_ASSERT("sa[2] == 2", sa[2] == 2);
+ _RS_ASSERT("sa[3] == 3", sa[3] == 3);
+ _RS_ASSERT("sa.length == 4", sa.length == 4);
+
+ int[] ia = s.get_ia();
+ _RS_ASSERT("ia[0] == 5", ia[0] == 5);
+ _RS_ASSERT("ia[1] == 8", ia[1] == 8);
+ _RS_ASSERT("ia[2] == 0", ia[2] == 0);
+ _RS_ASSERT("ia[3] == 0", ia[3] == 0);
+ _RS_ASSERT("ia.length == 4", ia.length == 4);
+
+ long[] la = s.get_la();
+ _RS_ASSERT("la[0] == 13", la[0] == 13);
+ _RS_ASSERT("la[1] == 21", la[1] == 21);
+ _RS_ASSERT("la.length == 4", la.length == 2);
+
+ long[] lla = s.get_lla();
+ _RS_ASSERT("lla[0] == 34", lla[0] == 34);
+ _RS_ASSERT("lla[1] == 0", lla[1] == 0);
+ _RS_ASSERT("lla[2] == 0", lla[2] == 0);
+ _RS_ASSERT("lla[3] == 0", lla[3] == 0);
+ _RS_ASSERT("lla.length == 4", lla.length == 4);
+
+ boolean[] ba = s.get_ba();
+ _RS_ASSERT("ba[0] == true", ba[0] == true);
+ _RS_ASSERT("ba[1] == false", ba[1] == false);
+ _RS_ASSERT("ba[2] == false", ba[2] == false);
+ _RS_ASSERT("ba.length == 3", ba.length == 3);
+ }
+
+ public void run() {
+ RenderScript pRS = RenderScript.create(mCtx);
+ ScriptC_array_init s = new ScriptC_array_init(pRS, mRes, R.raw.array_init);
+ pRS.setMessageHandler(mRsMessage);
+ checkInit(s);
+ s.invoke_array_init_test();
+ pRS.finish();
+ waitForMessage();
+ pRS.destroy();
+ passTest();
+ }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_element.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_element.java
new file mode 100644
index 0000000..3e2a2ca
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_element.java
@@ -0,0 +1,132 @@
+/*
+ * 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.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.renderscript.Element.*;
+import android.renderscript.Element.DataKind.*;
+import android.renderscript.Element.DataType.*;
+
+public class UT_element extends UnitTest {
+ private Resources mRes;
+
+ Element simpleElem;
+ Element complexElem;
+
+ final String subElemNames[] = {
+ "subElem0",
+ "subElem1",
+ "subElem2",
+ "arrayElem0",
+ "arrayElem1",
+ "subElem3",
+ "subElem4",
+ "subElem5",
+ "subElem6",
+ "subElem_7",
+ };
+
+ final int subElemArraySizes[] = {
+ 1,
+ 1,
+ 1,
+ 2,
+ 5,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ };
+
+ final int subElemOffsets[] = {
+ 0,
+ 4,
+ 8,
+ 12,
+ 20,
+ 40,
+ 44,
+ 48,
+ 64,
+ 80,
+ };
+
+ protected UT_element(RSTestCore rstc, Resources res, Context ctx) {
+ super(rstc, "Element", ctx);
+ mRes = res;
+ }
+
+ private void initializeGlobals(RenderScript RS, ScriptC_element s) {
+ simpleElem = Element.F32_3(RS);
+ complexElem = ScriptField_ComplexStruct.createElement(RS);
+ s.set_simpleElem(simpleElem);
+ s.set_complexElem(complexElem);
+
+ ScriptField_ComplexStruct data = new ScriptField_ComplexStruct(RS, 1);
+ s.bind_complexStruct(data);
+ }
+
+ private void testScriptSide(RenderScript pRS) {
+ ScriptC_element s = new ScriptC_element(pRS, mRes, R.raw.element);
+ pRS.setMessageHandler(mRsMessage);
+ initializeGlobals(pRS, s);
+ s.invoke_element_test();
+ pRS.finish();
+ waitForMessage();
+ }
+
+ private void testJavaSide(RenderScript RS) {
+
+ int subElemCount = simpleElem.getSubElementCount();
+ _RS_ASSERT("subElemCount == 0", subElemCount == 0);
+ _RS_ASSERT("simpleElem.getDataKind() == USER",
+ simpleElem.getDataKind() == DataKind.USER);
+ _RS_ASSERT("simpleElem.getDataType() == FLOAT_32",
+ simpleElem.getDataType() == DataType.FLOAT_32);
+
+ subElemCount = complexElem.getSubElementCount();
+ _RS_ASSERT("subElemCount == 10", subElemCount == 10);
+ _RS_ASSERT("complexElem.getDataKind() == USER",
+ complexElem.getDataKind() == DataKind.USER);
+ _RS_ASSERT("complexElemsimpleElem.getDataType() == NONE",
+ complexElem.getDataType() == DataType.NONE);
+ _RS_ASSERT("complexElem.getSizeBytes() == ScriptField_ComplexStruct.Item.sizeof",
+ complexElem.getSizeBytes() == ScriptField_ComplexStruct.Item.sizeof);
+
+ for (int i = 0; i < subElemCount; i ++) {
+ _RS_ASSERT("complexElem.getSubElement(i) != null",
+ complexElem.getSubElement(i) != null);
+ _RS_ASSERT("complexElem.getSubElementName(i).equals(subElemNames[i])",
+ complexElem.getSubElementName(i).equals(subElemNames[i]));
+ _RS_ASSERT("complexElem.getSubElementArraySize(i) == subElemArraySizes[i]",
+ complexElem.getSubElementArraySize(i) == subElemArraySizes[i]);
+ _RS_ASSERT("complexElem.getSubElementOffsetBytes(i) == subElemOffsets[i]",
+ complexElem.getSubElementOffsetBytes(i) == subElemOffsets[i]);
+ }
+ }
+
+ public void run() {
+ RenderScript pRS = RenderScript.create(mCtx);
+ testScriptSide(pRS);
+ testJavaSide(pRS);
+ passTest();
+ pRS.destroy();
+ }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_mesh.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_mesh.java
new file mode 100644
index 0000000..0c93702
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_mesh.java
@@ -0,0 +1,75 @@
+/*
+ * 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.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.renderscript.Mesh.*;
+
+public class UT_mesh extends UnitTest {
+ private Resources mRes;
+
+ Mesh mesh;
+
+ protected UT_mesh(RSTestCore rstc, Resources res, Context ctx) {
+ super(rstc, "Mesh", ctx);
+ mRes = res;
+ }
+
+ private void initializeGlobals(RenderScript RS, ScriptC_mesh s) {
+ Allocation vAlloc0 = Allocation.createSized(RS, Element.F32(RS), 10);
+ Allocation vAlloc1 = Allocation.createSized(RS, Element.F32_2(RS), 10);
+
+ Allocation iAlloc0 = Allocation.createSized(RS, Element.I16(RS), 10);
+ Allocation iAlloc2 = Allocation.createSized(RS, Element.I16(RS), 10);
+
+ Mesh.AllocationBuilder mBuilder = new Mesh.AllocationBuilder(RS);
+ mBuilder.addVertexAllocation(vAlloc0);
+ mBuilder.addVertexAllocation(vAlloc1);
+
+ mBuilder.addIndexSetAllocation(iAlloc0, Primitive.POINT);
+ mBuilder.addIndexSetType(Primitive.LINE);
+ mBuilder.addIndexSetAllocation(iAlloc2, Primitive.TRIANGLE);
+
+ s.set_mesh(mBuilder.create());
+ s.set_vertexAlloc0(vAlloc0);
+ s.set_vertexAlloc1(vAlloc1);
+ s.set_indexAlloc0(iAlloc0);
+ s.set_indexAlloc2(iAlloc2);
+ }
+
+ private void testScriptSide(RenderScript pRS) {
+ ScriptC_mesh s = new ScriptC_mesh(pRS, mRes, R.raw.mesh);
+ pRS.setMessageHandler(mRsMessage);
+ initializeGlobals(pRS, s);
+ s.invoke_mesh_test();
+ pRS.finish();
+ waitForMessage();
+ }
+
+ private void testJavaSide(RenderScript RS) {
+ }
+
+ public void run() {
+ RenderScript pRS = RenderScript.create(mCtx);
+ testScriptSide(pRS);
+ testJavaSide(pRS);
+ passTest();
+ pRS.destroy();
+ }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_raster.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_raster.java
new file mode 100644
index 0000000..1de4d71
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_raster.java
@@ -0,0 +1,81 @@
+/*
+ * 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.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.renderscript.ProgramRaster;
+import android.renderscript.ProgramRaster.CullMode;
+
+public class UT_program_raster extends UnitTest {
+ private Resources mRes;
+
+ ProgramRaster pointSpriteEnabled;
+ ProgramRaster cullMode;
+
+ protected UT_program_raster(RSTestCore rstc, Resources res, Context ctx) {
+ super(rstc, "ProgramRaster", ctx);
+ mRes = res;
+ }
+
+ private ProgramRaster.Builder getDefaultBuilder(RenderScript RS) {
+ ProgramRaster.Builder b = new ProgramRaster.Builder(RS);
+ b.setCullMode(CullMode.BACK);
+ b.setPointSpriteEnabled(false);
+ return b;
+ }
+
+ private void initializeGlobals(RenderScript RS, ScriptC_program_raster s) {
+ ProgramRaster.Builder b = getDefaultBuilder(RS);
+ pointSpriteEnabled = b.setPointSpriteEnabled(true).create();
+ b = getDefaultBuilder(RS);
+ cullMode = b.setCullMode(CullMode.FRONT).create();
+
+ s.set_pointSpriteEnabled(pointSpriteEnabled);
+ s.set_cullMode(cullMode);
+ }
+
+ private void testScriptSide(RenderScript pRS) {
+ ScriptC_program_raster s = new ScriptC_program_raster(pRS, mRes, R.raw.program_raster);
+ pRS.setMessageHandler(mRsMessage);
+ initializeGlobals(pRS, s);
+ s.invoke_program_raster_test();
+ pRS.finish();
+ waitForMessage();
+ }
+
+ private void testJavaSide(RenderScript RS) {
+ _RS_ASSERT("pointSpriteEnabled.getPointSpriteEnabled() == true",
+ pointSpriteEnabled.getPointSpriteEnabled() == true);
+ _RS_ASSERT("pointSpriteEnabled.getCullMode() == ProgramRaster.CullMode.BACK",
+ pointSpriteEnabled.getCullMode() == ProgramRaster.CullMode.BACK);
+
+ _RS_ASSERT("cullMode.getPointSpriteEnabled() == false",
+ cullMode.getPointSpriteEnabled() == false);
+ _RS_ASSERT("cullMode.getCullMode() == ProgramRaster.CullMode.FRONT",
+ cullMode.getCullMode() == ProgramRaster.CullMode.FRONT);
+ }
+
+ public void run() {
+ RenderScript pRS = RenderScript.create(mCtx);
+ testScriptSide(pRS);
+ testJavaSide(pRS);
+ passTest();
+ pRS.destroy();
+ }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_store.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_store.java
new file mode 100644
index 0000000..72a401d
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_store.java
@@ -0,0 +1,175 @@
+/*
+ * 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.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.renderscript.ProgramStore.BlendDstFunc;
+import android.renderscript.ProgramStore.BlendSrcFunc;
+import android.renderscript.ProgramStore.Builder;
+import android.renderscript.ProgramStore.DepthFunc;
+
+public class UT_program_store extends UnitTest {
+ private Resources mRes;
+
+ ProgramStore ditherEnable;
+ ProgramStore colorRWriteEnable;
+ ProgramStore colorGWriteEnable;
+ ProgramStore colorBWriteEnable;
+ ProgramStore colorAWriteEnable;
+ ProgramStore blendSrc;
+ ProgramStore blendDst;
+ ProgramStore depthWriteEnable;
+ ProgramStore depthFunc;
+
+ protected UT_program_store(RSTestCore rstc, Resources res, Context ctx) {
+ super(rstc, "ProgramStore", ctx);
+ mRes = res;
+ }
+
+ private ProgramStore.Builder getDefaultBuilder(RenderScript RS) {
+ ProgramStore.Builder b = new ProgramStore.Builder(RS);
+ b.setBlendFunc(ProgramStore.BlendSrcFunc.ZERO, ProgramStore.BlendDstFunc.ZERO);
+ b.setColorMaskEnabled(false, false, false, false);
+ b.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
+ b.setDepthMaskEnabled(false);
+ b.setDitherEnabled(false);
+ return b;
+ }
+
+ private void initializeGlobals(RenderScript RS, ScriptC_program_store s) {
+ ProgramStore.Builder b = getDefaultBuilder(RS);
+ ditherEnable = b.setDitherEnabled(true).create();
+
+ b = getDefaultBuilder(RS);
+ colorRWriteEnable = b.setColorMaskEnabled(true, false, false, false).create();
+
+ b = getDefaultBuilder(RS);
+ colorGWriteEnable = b.setColorMaskEnabled(false, true, false, false).create();
+
+ b = getDefaultBuilder(RS);
+ colorBWriteEnable = b.setColorMaskEnabled(false, false, true, false).create();
+
+ b = getDefaultBuilder(RS);
+ colorAWriteEnable = b.setColorMaskEnabled(false, false, false, true).create();
+
+ b = getDefaultBuilder(RS);
+ blendSrc = b.setBlendFunc(ProgramStore.BlendSrcFunc.DST_COLOR,
+ ProgramStore.BlendDstFunc.ZERO).create();
+
+ b = getDefaultBuilder(RS);
+ blendDst = b.setBlendFunc(ProgramStore.BlendSrcFunc.ZERO,
+ ProgramStore.BlendDstFunc.DST_ALPHA).create();
+
+ b = getDefaultBuilder(RS);
+ depthWriteEnable = b.setDepthMaskEnabled(true).create();
+
+ b = getDefaultBuilder(RS);
+ depthFunc = b.setDepthFunc(ProgramStore.DepthFunc.GREATER).create();
+
+ s.set_ditherEnable(ditherEnable);
+ s.set_colorRWriteEnable(colorRWriteEnable);
+ s.set_colorGWriteEnable(colorGWriteEnable);
+ s.set_colorBWriteEnable(colorBWriteEnable);
+ s.set_colorAWriteEnable(colorAWriteEnable);
+ s.set_blendSrc(blendSrc);
+ s.set_blendDst(blendDst);
+ s.set_depthWriteEnable(depthWriteEnable);
+ s.set_depthFunc(depthFunc);
+ }
+
+ private void testScriptSide(RenderScript pRS) {
+ ScriptC_program_store s = new ScriptC_program_store(pRS, mRes, R.raw.program_store);
+ pRS.setMessageHandler(mRsMessage);
+ initializeGlobals(pRS, s);
+ s.invoke_program_store_test();
+ pRS.finish();
+ waitForMessage();
+ }
+
+ void checkObject(ProgramStore ps,
+ boolean depthMask,
+ DepthFunc df,
+ BlendSrcFunc bsf,
+ BlendDstFunc bdf,
+ boolean R,
+ boolean G,
+ boolean B,
+ boolean A,
+ boolean dither) {
+ _RS_ASSERT("ps.getDepthMaskEnabled() == depthMask", ps.getDepthMaskEnabled() == depthMask);
+ _RS_ASSERT("ps.getDepthFunc() == df", ps.getDepthFunc() == df);
+ _RS_ASSERT("ps.getBlendSrcFunc() == bsf", ps.getBlendSrcFunc() == bsf);
+ _RS_ASSERT("ps.getBlendDstFunc() == bdf", ps.getBlendDstFunc() == bdf);
+ _RS_ASSERT("ps.getColorMaskREnabled() == R", ps.getColorMaskREnabled() == R);
+ _RS_ASSERT("ps.getColorMaskGEnabled() == G", ps.getColorMaskGEnabled() == G);
+ _RS_ASSERT("ps.getColorMaskBEnabled() == B", ps.getColorMaskBEnabled() == B);
+ _RS_ASSERT("ps.getColorMaskAEnabled() == A", ps.getColorMaskAEnabled() == A);
+ _RS_ASSERT("ps.getDitherEnabled() == dither", ps.getDitherEnabled() == dither);
+ }
+
+ void varyBuilderColorAndDither(ProgramStore.Builder pb,
+ boolean depthMask,
+ DepthFunc df,
+ BlendSrcFunc bsf,
+ BlendDstFunc bdf) {
+ for (int r = 0; r <= 1; r++) {
+ boolean isR = (r == 1);
+ for (int g = 0; g <= 1; g++) {
+ boolean isG = (g == 1);
+ for (int b = 0; b <= 1; b++) {
+ boolean isB = (b == 1);
+ for (int a = 0; a <= 1; a++) {
+ boolean isA = (a == 1);
+ for (int dither = 0; dither <= 1; dither++) {
+ boolean isDither = (dither == 1);
+ pb.setDitherEnabled(isDither);
+ pb.setColorMaskEnabled(isR, isG, isB, isA);
+ ProgramStore ps = pb.create();
+ checkObject(ps, depthMask, df, bsf, bdf, isR, isG, isB, isA, isDither);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void testJavaSide(RenderScript RS) {
+ for (int depth = 0; depth <= 1; depth++) {
+ boolean depthMask = (depth == 1);
+ for (DepthFunc df : DepthFunc.values()) {
+ for (BlendSrcFunc bsf : BlendSrcFunc.values()) {
+ for (BlendDstFunc bdf : BlendDstFunc.values()) {
+ ProgramStore.Builder b = new ProgramStore.Builder(RS);
+ b.setDepthFunc(df);
+ b.setDepthMaskEnabled(depthMask);
+ b.setBlendFunc(bsf, bdf);
+ varyBuilderColorAndDither(b, depthMask, df, bsf, bdf);
+ }
+ }
+ }
+ }
+ }
+
+ public void run() {
+ RenderScript pRS = RenderScript.create(mCtx);
+ testJavaSide(pRS);
+ testScriptSide(pRS);
+ pRS.destroy();
+ }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_sampler.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_sampler.java
new file mode 100644
index 0000000..c328cf6
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_sampler.java
@@ -0,0 +1,150 @@
+/*
+ * 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.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.renderscript.Sampler;
+import android.renderscript.Sampler.Value;
+
+public class UT_sampler extends UnitTest {
+ private Resources mRes;
+
+ Sampler minification;
+ Sampler magnification;
+ Sampler wrapS;
+ Sampler wrapT;
+ Sampler anisotropy;
+
+ protected UT_sampler(RSTestCore rstc, Resources res, Context ctx) {
+ super(rstc, "Sampler", ctx);
+ mRes = res;
+ }
+
+ private Sampler.Builder getDefaultBuilder(RenderScript RS) {
+ Sampler.Builder b = new Sampler.Builder(RS);
+ b.setMinification(Value.NEAREST);
+ b.setMagnification(Value.NEAREST);
+ b.setWrapS(Value.CLAMP);
+ b.setWrapT(Value.CLAMP);
+ b.setAnisotropy(1.0f);
+ return b;
+ }
+
+ private void initializeGlobals(RenderScript RS, ScriptC_sampler s) {
+ Sampler.Builder b = getDefaultBuilder(RS);
+ b.setMinification(Value.LINEAR_MIP_LINEAR);
+ minification = b.create();
+
+ b = getDefaultBuilder(RS);
+ b.setMagnification(Value.LINEAR);
+ magnification = b.create();
+
+ b = getDefaultBuilder(RS);
+ b.setWrapS(Value.WRAP);
+ wrapS = b.create();
+
+ b = getDefaultBuilder(RS);
+ b.setWrapT(Value.WRAP);
+ wrapT = b.create();
+
+ b = getDefaultBuilder(RS);
+ b.setAnisotropy(8.0f);
+ anisotropy = b.create();
+
+ s.set_minification(minification);
+ s.set_magnification(magnification);
+ s.set_wrapS(wrapS);
+ s.set_wrapT(wrapT);
+ s.set_anisotropy(anisotropy);
+ }
+
+ private void testScriptSide(RenderScript pRS) {
+ ScriptC_sampler s = new ScriptC_sampler(pRS, mRes, R.raw.sampler);
+ pRS.setMessageHandler(mRsMessage);
+ initializeGlobals(pRS, s);
+ s.invoke_sampler_test();
+ pRS.finish();
+ waitForMessage();
+ }
+
+ private void testJavaSide(RenderScript RS) {
+ _RS_ASSERT("minification.getMagnification() == Sampler.Value.NEAREST",
+ minification.getMagnification() == Sampler.Value.NEAREST);
+ _RS_ASSERT("minification.getMinification() == Sampler.Value.LINEAR_MIP_LINEAR",
+ minification.getMinification() == Sampler.Value.LINEAR_MIP_LINEAR);
+ _RS_ASSERT("minification.getWrapS() == Sampler.Value.CLAMP",
+ minification.getWrapS() == Sampler.Value.CLAMP);
+ _RS_ASSERT("minification.getWrapT() == Sampler.Value.CLAMP",
+ minification.getWrapT() == Sampler.Value.CLAMP);
+ _RS_ASSERT("minification.getAnisotropy() == 1.0f",
+ minification.getAnisotropy() == 1.0f);
+
+ _RS_ASSERT("magnification.getMagnification() == Sampler.Value.LINEAR",
+ magnification.getMagnification() == Sampler.Value.LINEAR);
+ _RS_ASSERT("magnification.getMinification() == Sampler.Value.NEAREST",
+ magnification.getMinification() == Sampler.Value.NEAREST);
+ _RS_ASSERT("magnification.getWrapS() == Sampler.Value.CLAMP",
+ magnification.getWrapS() == Sampler.Value.CLAMP);
+ _RS_ASSERT("magnification.getWrapT() == Sampler.Value.CLAMP",
+ magnification.getWrapT() == Sampler.Value.CLAMP);
+ _RS_ASSERT("magnification.getAnisotropy() == 1.0f",
+ magnification.getAnisotropy() == 1.0f);
+
+ _RS_ASSERT("wrapS.getMagnification() == Sampler.Value.NEAREST",
+ wrapS.getMagnification() == Sampler.Value.NEAREST);
+ _RS_ASSERT("wrapS.getMinification() == Sampler.Value.NEAREST",
+ wrapS.getMinification() == Sampler.Value.NEAREST);
+ _RS_ASSERT("wrapS.getWrapS() == Sampler.Value.WRAP",
+ wrapS.getWrapS() == Sampler.Value.WRAP);
+ _RS_ASSERT("wrapS.getWrapT() == Sampler.Value.CLAMP",
+ wrapS.getWrapT() == Sampler.Value.CLAMP);
+ _RS_ASSERT("wrapS.getAnisotropy() == 1.0f",
+ wrapS.getAnisotropy() == 1.0f);
+
+ _RS_ASSERT("wrapT.getMagnification() == Sampler.Value.NEAREST",
+ wrapT.getMagnification() == Sampler.Value.NEAREST);
+ _RS_ASSERT("wrapT.getMinification() == Sampler.Value.NEAREST",
+ wrapT.getMinification() == Sampler.Value.NEAREST);
+ _RS_ASSERT("wrapT.getWrapS() == Sampler.Value.CLAMP",
+ wrapT.getWrapS() == Sampler.Value.CLAMP);
+ _RS_ASSERT("wrapT.getWrapT() == Sampler.Value.WRAP",
+ wrapT.getWrapT() == Sampler.Value.WRAP);
+ _RS_ASSERT("wrapT.getAnisotropy() == 1.0f",
+ wrapT.getAnisotropy() == 1.0f);
+
+ _RS_ASSERT("anisotropy.getMagnification() == Sampler.Value.NEAREST",
+ anisotropy.getMagnification() == Sampler.Value.NEAREST);
+ _RS_ASSERT("anisotropy.getMinification() == Sampler.Value.NEAREST",
+ anisotropy.getMinification() == Sampler.Value.NEAREST);
+ _RS_ASSERT("anisotropy.getWrapS() == Sampler.Value.CLAMP",
+ anisotropy.getWrapS() == Sampler.Value.CLAMP);
+ _RS_ASSERT("anisotropy.getWrapT() == Sampler.Value.CLAMP",
+ anisotropy.getWrapT() == Sampler.Value.CLAMP);
+ _RS_ASSERT("anisotropy.getAnisotropy() == 1.0f",
+ anisotropy.getAnisotropy() == 8.0f);
+ }
+
+ public void run() {
+ RenderScript pRS = RenderScript.create(mCtx);
+ testScriptSide(pRS);
+ testJavaSide(pRS);
+ passTest();
+ pRS.destroy();
+ }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UnitTest.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UnitTest.java
index edff83f..fbac124 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UnitTest.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UnitTest.java
@@ -58,8 +58,8 @@
protected void _RS_ASSERT(String message, boolean b) {
if(b == false) {
- result = -1;
Log.e(name, message + " FAILED");
+ failTest();
}
}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/array_init.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/array_init.rs
new file mode 100644
index 0000000..842249a
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/array_init.rs
@@ -0,0 +1,58 @@
+#include "shared.rsh"
+
+// Testing constant array initialization
+float fa[4] = {1.0, 9.9999f};
+double da[2] = {7.0, 8.88888};
+char ca[4] = {'a', 7, 'b', 'c'};
+short sa[4] = {1, 1, 2, 3};
+int ia[4] = {5, 8};
+long la[2] = {13, 21};
+long long lla[4] = {34};
+bool ba[3] = {true, false};
+
+void array_init_test() {
+ bool failed = false;
+
+ _RS_ASSERT(fa[0] == 1.0);
+ _RS_ASSERT(fa[1] == 9.9999f);
+ _RS_ASSERT(fa[2] == 0);
+ _RS_ASSERT(fa[3] == 0);
+
+ _RS_ASSERT(da[0] == 7.0);
+ _RS_ASSERT(da[1] == 8.88888);
+
+ _RS_ASSERT(ca[0] == 'a');
+ _RS_ASSERT(ca[1] == 7);
+ _RS_ASSERT(ca[2] == 'b');
+ _RS_ASSERT(ca[3] == 'c');
+
+ _RS_ASSERT(sa[0] == 1);
+ _RS_ASSERT(sa[1] == 1);
+ _RS_ASSERT(sa[2] == 2);
+ _RS_ASSERT(sa[3] == 3);
+
+ _RS_ASSERT(ia[0] == 5);
+ _RS_ASSERT(ia[1] == 8);
+ _RS_ASSERT(ia[2] == 0);
+ _RS_ASSERT(ia[3] == 0);
+
+ _RS_ASSERT(la[0] == 13);
+ _RS_ASSERT(la[1] == 21);
+
+ _RS_ASSERT(lla[0] == 34);
+ _RS_ASSERT(lla[1] == 0);
+ _RS_ASSERT(lla[2] == 0);
+ _RS_ASSERT(lla[3] == 0);
+
+ _RS_ASSERT(ba[0] == true);
+ _RS_ASSERT(ba[1] == false);
+ _RS_ASSERT(ba[2] == false);
+
+ if (failed) {
+ rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+ }
+ else {
+ rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+ }
+}
+
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/element.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/element.rs
new file mode 100644
index 0000000..0c42d84
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/element.rs
@@ -0,0 +1,158 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+
+rs_element simpleElem;
+rs_element complexElem;
+typedef struct ComplexStruct {
+ float subElem0;
+ float subElem1;
+ int subElem2;
+ float arrayElem0[2];
+ int arrayElem1[5];
+ char subElem3;
+ float subElem4;
+ float2 subElem5;
+ float3 subElem6;
+ float4 subElem_7;
+} ComplexStruct_t;
+
+ComplexStruct_t *complexStruct;
+
+static const char *subElemNames[] = {
+ "subElem0",
+ "subElem1",
+ "subElem2",
+ "arrayElem0",
+ "arrayElem1",
+ "subElem3",
+ "subElem4",
+ "subElem5",
+ "subElem6",
+ "subElem_7",
+};
+
+static uint32_t subElemNamesSizes[] = {
+ 8,
+ 8,
+ 8,
+ 10,
+ 10,
+ 8,
+ 8,
+ 8,
+ 8,
+ 9,
+};
+
+static uint32_t subElemArraySizes[] = {
+ 1,
+ 1,
+ 1,
+ 2,
+ 5,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+};
+
+static void resetStruct() {
+ uint8_t *bytePtr = (uint8_t*)complexStruct;
+ uint32_t sizeOfStruct = sizeof(*complexStruct);
+ for(uint32_t i = 0; i < sizeOfStruct; i ++) {
+ bytePtr[i] = 0;
+ }
+}
+
+static bool equals(const char *name0, const char * name1, uint32_t len) {
+ for (uint32_t i = 0; i < len; i ++) {
+ if (name0[i] != name1[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool test_element_getters() {
+ bool failed = false;
+
+ uint32_t subElemOffsets[10];
+ uint32_t index = 0;
+ subElemOffsets[index++] = (uint32_t)&complexStruct->subElem0 - (uint32_t)complexStruct;
+ subElemOffsets[index++] = (uint32_t)&complexStruct->subElem1 - (uint32_t)complexStruct;
+ subElemOffsets[index++] = (uint32_t)&complexStruct->subElem2 - (uint32_t)complexStruct;
+ subElemOffsets[index++] = (uint32_t)&complexStruct->arrayElem0 - (uint32_t)complexStruct;
+ subElemOffsets[index++] = (uint32_t)&complexStruct->arrayElem1 - (uint32_t)complexStruct;
+ subElemOffsets[index++] = (uint32_t)&complexStruct->subElem3 - (uint32_t)complexStruct;
+ subElemOffsets[index++] = (uint32_t)&complexStruct->subElem4 - (uint32_t)complexStruct;
+ subElemOffsets[index++] = (uint32_t)&complexStruct->subElem5 - (uint32_t)complexStruct;
+ subElemOffsets[index++] = (uint32_t)&complexStruct->subElem6 - (uint32_t)complexStruct;
+ subElemOffsets[index++] = (uint32_t)&complexStruct->subElem_7 - (uint32_t)complexStruct;
+
+ uint32_t subElemCount = rsElementGetSubElementCount(simpleElem);
+ _RS_ASSERT(subElemCount == 0);
+ _RS_ASSERT(rsElementGetDataKind(simpleElem) == RS_KIND_USER);
+ _RS_ASSERT(rsElementGetDataType(simpleElem) == RS_TYPE_FLOAT_32);
+ _RS_ASSERT(rsElementGetVectorSize(simpleElem) == 3);
+
+ subElemCount = rsElementGetSubElementCount(complexElem);
+ _RS_ASSERT(subElemCount == 10);
+ _RS_ASSERT(rsElementGetDataKind(complexElem) == RS_KIND_USER);
+ _RS_ASSERT(rsElementGetDataType(complexElem) == RS_TYPE_NONE);
+ _RS_ASSERT(rsElementGetVectorSize(complexElem) == 1);
+ _RS_ASSERT(rsElementGetSizeBytes(complexElem) == sizeof(*complexStruct));
+
+ char buffer[64];
+ for (uint32_t i = 0; i < subElemCount; i ++) {
+ rs_element subElem = rsElementGetSubElement(complexElem, i);
+ _RS_ASSERT(rsIsObject(subElem));
+
+ _RS_ASSERT(rsElementGetSubElementNameLength(complexElem, i) == subElemNamesSizes[i] + 1);
+
+ uint32_t written = rsElementGetSubElementName(complexElem, i, buffer, 64);
+ _RS_ASSERT(written == subElemNamesSizes[i]);
+ _RS_ASSERT(equals(buffer, subElemNames[i], written));
+
+ _RS_ASSERT(rsElementGetSubElementArraySize(complexElem, i) == subElemArraySizes[i]);
+ _RS_ASSERT(rsElementGetSubElementOffsetBytes(complexElem, i) == subElemOffsets[i]);
+ }
+
+ // Tests error checking
+ rs_element subElem = rsElementGetSubElement(complexElem, subElemCount);
+ _RS_ASSERT(!rsIsObject(subElem));
+
+ _RS_ASSERT(rsElementGetSubElementNameLength(complexElem, subElemCount) == 0);
+
+ _RS_ASSERT(rsElementGetSubElementName(complexElem, subElemCount, buffer, 64) == 0);
+ _RS_ASSERT(rsElementGetSubElementName(complexElem, 0, NULL, 64) == 0);
+ _RS_ASSERT(rsElementGetSubElementName(complexElem, 0, buffer, 0) == 0);
+ uint32_t written = rsElementGetSubElementName(complexElem, 0, buffer, 5);
+ _RS_ASSERT(written == 4);
+ _RS_ASSERT(buffer[4] == '\0');
+
+ _RS_ASSERT(rsElementGetSubElementArraySize(complexElem, subElemCount) == 0);
+ _RS_ASSERT(rsElementGetSubElementOffsetBytes(complexElem, subElemCount) == 0);
+
+ if (failed) {
+ rsDebug("test_element_getters FAILED", 0);
+ }
+ else {
+ rsDebug("test_element_getters PASSED", 0);
+ }
+
+ return failed;
+}
+
+void element_test() {
+ bool failed = false;
+ failed |= test_element_getters();
+
+ if (failed) {
+ rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+ }
+ else {
+ rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+ }
+}
+
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/mesh.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/mesh.rs
new file mode 100644
index 0000000..627ab99
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/mesh.rs
@@ -0,0 +1,64 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+
+rs_mesh mesh;
+rs_allocation vertexAlloc0;
+rs_allocation vertexAlloc1;
+
+rs_allocation indexAlloc0;
+rs_allocation indexAlloc2;
+
+static bool test_mesh_getters() {
+ bool failed = false;
+
+ _RS_ASSERT(rsMeshGetVertexAllocationCount(mesh) == 2);
+ _RS_ASSERT(rsMeshGetPrimitiveCount(mesh) == 3);
+
+ rs_allocation meshV0 = rsMeshGetVertexAllocation(mesh, 0);
+ rs_allocation meshV1 = rsMeshGetVertexAllocation(mesh, 1);
+ rs_allocation meshV2 = rsMeshGetVertexAllocation(mesh, 2);
+ _RS_ASSERT(meshV0.p == vertexAlloc0.p);
+ _RS_ASSERT(meshV1.p == vertexAlloc1.p);
+ _RS_ASSERT(!rsIsObject(meshV2));
+
+ rs_allocation meshI0 = rsMeshGetIndexAllocation(mesh, 0);
+ rs_allocation meshI1 = rsMeshGetIndexAllocation(mesh, 1);
+ rs_allocation meshI2 = rsMeshGetIndexAllocation(mesh, 2);
+ rs_allocation meshI3 = rsMeshGetIndexAllocation(mesh, 3);
+ _RS_ASSERT(meshI0.p == indexAlloc0.p);
+ _RS_ASSERT(!rsIsObject(meshI1));
+ _RS_ASSERT(meshI2.p == indexAlloc2.p);
+ _RS_ASSERT(!rsIsObject(meshI3));
+
+ rs_primitive p0 = rsMeshGetPrimitive(mesh, 0);
+ rs_primitive p1 = rsMeshGetPrimitive(mesh, 1);
+ rs_primitive p2 = rsMeshGetPrimitive(mesh, 2);
+ rs_primitive p3 = rsMeshGetPrimitive(mesh, 3);
+
+ _RS_ASSERT(p0 == RS_PRIMITIVE_POINT);
+ _RS_ASSERT(p1 == RS_PRIMITIVE_LINE);
+ _RS_ASSERT(p2 == RS_PRIMITIVE_TRIANGLE);
+ _RS_ASSERT(p3 == RS_PRIMITIVE_INVALID);
+
+ if (failed) {
+ rsDebug("test_mesh_getters FAILED", 0);
+ }
+ else {
+ rsDebug("test_mesh_getters PASSED", 0);
+ }
+
+ return failed;
+}
+
+void mesh_test() {
+ bool failed = false;
+ failed |= test_mesh_getters();
+
+ if (failed) {
+ rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+ }
+ else {
+ rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+ }
+}
+
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/program_raster.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/program_raster.rs
new file mode 100644
index 0000000..11b8c30
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/program_raster.rs
@@ -0,0 +1,37 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+
+rs_program_raster pointSpriteEnabled;
+rs_program_raster cullMode;
+
+static bool test_program_raster_getters() {
+ bool failed = false;
+
+ _RS_ASSERT(rsgProgramRasterGetPointSpriteEnabled(pointSpriteEnabled) == true);
+ _RS_ASSERT(rsgProgramRasterGetCullMode(pointSpriteEnabled) == RS_CULL_BACK);
+
+ _RS_ASSERT(rsgProgramRasterGetPointSpriteEnabled(cullMode) == false);
+ _RS_ASSERT(rsgProgramRasterGetCullMode(cullMode) == RS_CULL_FRONT);
+
+ if (failed) {
+ rsDebug("test_program_raster_getters FAILED", 0);
+ }
+ else {
+ rsDebug("test_program_raster_getters PASSED", 0);
+ }
+
+ return failed;
+}
+
+void program_raster_test() {
+ bool failed = false;
+ failed |= test_program_raster_getters();
+
+ if (failed) {
+ rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+ }
+ else {
+ rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+ }
+}
+
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/program_store.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/program_store.rs
new file mode 100644
index 0000000..3cd8a20
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/program_store.rs
@@ -0,0 +1,128 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+
+rs_program_store ditherEnable;
+rs_program_store colorRWriteEnable;
+rs_program_store colorGWriteEnable;
+rs_program_store colorBWriteEnable;
+rs_program_store colorAWriteEnable;
+rs_program_store blendSrc;
+rs_program_store blendDst;
+rs_program_store depthWriteEnable;
+rs_program_store depthFunc;
+
+static bool test_program_store_getters() {
+ bool failed = false;
+
+ _RS_ASSERT(rsgProgramStoreGetDepthFunc(depthFunc) == RS_DEPTH_FUNC_GREATER);
+ _RS_ASSERT(rsgProgramStoreGetDepthMask(depthFunc) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskR(depthFunc) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskG(depthFunc) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskB(depthFunc) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskA(depthFunc) == false);
+ _RS_ASSERT(rsgProgramStoreGetDitherEnabled(depthFunc) == false);
+ _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(depthFunc) == RS_BLEND_SRC_ZERO);
+ _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(depthFunc) == RS_BLEND_DST_ZERO);
+
+ _RS_ASSERT(rsgProgramStoreGetDepthFunc(depthWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+ _RS_ASSERT(rsgProgramStoreGetDepthMask(depthWriteEnable) == true);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskR(depthWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskG(depthWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskB(depthWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskA(depthWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetDitherEnabled(depthWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(depthWriteEnable) == RS_BLEND_SRC_ZERO);
+ _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(depthWriteEnable) == RS_BLEND_DST_ZERO);
+
+ _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorRWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+ _RS_ASSERT(rsgProgramStoreGetDepthMask(colorRWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskR(colorRWriteEnable) == true);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskG(colorRWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskB(colorRWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskA(colorRWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetDitherEnabled(colorRWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorRWriteEnable) == RS_BLEND_SRC_ZERO);
+ _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorRWriteEnable) == RS_BLEND_DST_ZERO);
+
+ _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorGWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+ _RS_ASSERT(rsgProgramStoreGetDepthMask(colorGWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskR(colorGWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskG(colorGWriteEnable) == true);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskB(colorGWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskA(colorGWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetDitherEnabled(colorGWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorGWriteEnable) == RS_BLEND_SRC_ZERO);
+ _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorGWriteEnable) == RS_BLEND_DST_ZERO);
+
+ _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorBWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+ _RS_ASSERT(rsgProgramStoreGetDepthMask(colorBWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskR(colorBWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskG(colorBWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskB(colorBWriteEnable) == true);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskA(colorBWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetDitherEnabled(colorBWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorBWriteEnable) == RS_BLEND_SRC_ZERO);
+ _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorBWriteEnable) == RS_BLEND_DST_ZERO);
+
+ _RS_ASSERT(rsgProgramStoreGetDepthFunc(colorAWriteEnable) == RS_DEPTH_FUNC_ALWAYS);
+ _RS_ASSERT(rsgProgramStoreGetDepthMask(colorAWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskR(colorAWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskG(colorAWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskB(colorAWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskA(colorAWriteEnable) == true);
+ _RS_ASSERT(rsgProgramStoreGetDitherEnabled(colorAWriteEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(colorAWriteEnable) == RS_BLEND_SRC_ZERO);
+ _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(colorAWriteEnable) == RS_BLEND_DST_ZERO);
+
+ _RS_ASSERT(rsgProgramStoreGetDepthFunc(ditherEnable) == RS_DEPTH_FUNC_ALWAYS);
+ _RS_ASSERT(rsgProgramStoreGetDepthMask(ditherEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskR(ditherEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskG(ditherEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskB(ditherEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskA(ditherEnable) == false);
+ _RS_ASSERT(rsgProgramStoreGetDitherEnabled(ditherEnable) == true);
+ _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(ditherEnable) == RS_BLEND_SRC_ZERO);
+ _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(ditherEnable) == RS_BLEND_DST_ZERO);
+
+ _RS_ASSERT(rsgProgramStoreGetDepthFunc(blendSrc) == RS_DEPTH_FUNC_ALWAYS);
+ _RS_ASSERT(rsgProgramStoreGetDepthMask(blendSrc) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskR(blendSrc) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskG(blendSrc) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskB(blendSrc) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskA(blendSrc) == false);
+ _RS_ASSERT(rsgProgramStoreGetDitherEnabled(blendSrc) == false);
+ _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(blendSrc) == RS_BLEND_SRC_DST_COLOR);
+ _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(blendSrc) == RS_BLEND_DST_ZERO);
+
+ _RS_ASSERT(rsgProgramStoreGetDepthFunc(blendDst) == RS_DEPTH_FUNC_ALWAYS);
+ _RS_ASSERT(rsgProgramStoreGetDepthMask(blendDst) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskR(blendDst) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskG(blendDst) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskB(blendDst) == false);
+ _RS_ASSERT(rsgProgramStoreGetColorMaskA(blendDst) == false);
+ _RS_ASSERT(rsgProgramStoreGetDitherEnabled(blendDst) == false);
+ _RS_ASSERT(rsgProgramStoreGetBlendSrcFunc(blendDst) == RS_BLEND_SRC_ZERO);
+ _RS_ASSERT(rsgProgramStoreGetBlendDstFunc(blendDst) == RS_BLEND_DST_DST_ALPHA);
+
+ if (failed) {
+ rsDebug("test_program_store_getters FAILED", 0);
+ }
+ else {
+ rsDebug("test_program_store_getters PASSED", 0);
+ }
+
+ return failed;
+}
+
+void program_store_test() {
+ bool failed = false;
+ failed |= test_program_store_getters();
+
+ if (failed) {
+ rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+ }
+ else {
+ rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+ }
+}
+
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/sampler.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/sampler.rs
new file mode 100644
index 0000000..ac9a549
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/sampler.rs
@@ -0,0 +1,63 @@
+#include "shared.rsh"
+#include "rs_graphics.rsh"
+rs_sampler minification;
+rs_sampler magnification;
+rs_sampler wrapS;
+rs_sampler wrapT;
+rs_sampler anisotropy;
+
+static bool test_sampler_getters() {
+ bool failed = false;
+
+ _RS_ASSERT(rsgSamplerGetMagnification(minification) == RS_SAMPLER_NEAREST);
+ _RS_ASSERT(rsgSamplerGetMinification(minification) == RS_SAMPLER_LINEAR_MIP_LINEAR);
+ _RS_ASSERT(rsgSamplerGetWrapS(minification) == RS_SAMPLER_CLAMP);
+ _RS_ASSERT(rsgSamplerGetWrapT(minification) == RS_SAMPLER_CLAMP);
+ _RS_ASSERT(rsgSamplerGetAnisotropy(minification) == 1.0f);
+
+ _RS_ASSERT(rsgSamplerGetMagnification(magnification) == RS_SAMPLER_LINEAR);
+ _RS_ASSERT(rsgSamplerGetMinification(magnification) == RS_SAMPLER_NEAREST);
+ _RS_ASSERT(rsgSamplerGetWrapS(magnification) == RS_SAMPLER_CLAMP);
+ _RS_ASSERT(rsgSamplerGetWrapT(magnification) == RS_SAMPLER_CLAMP);
+ _RS_ASSERT(rsgSamplerGetAnisotropy(magnification) == 1.0f);
+
+ _RS_ASSERT(rsgSamplerGetMagnification(wrapS) == RS_SAMPLER_NEAREST);
+ _RS_ASSERT(rsgSamplerGetMinification(wrapS) == RS_SAMPLER_NEAREST);
+ _RS_ASSERT(rsgSamplerGetWrapS(wrapS) == RS_SAMPLER_WRAP);
+ _RS_ASSERT(rsgSamplerGetWrapT(wrapS) == RS_SAMPLER_CLAMP);
+ _RS_ASSERT(rsgSamplerGetAnisotropy(wrapS) == 1.0f);
+
+ _RS_ASSERT(rsgSamplerGetMagnification(wrapT) == RS_SAMPLER_NEAREST);
+ _RS_ASSERT(rsgSamplerGetMinification(wrapT) == RS_SAMPLER_NEAREST);
+ _RS_ASSERT(rsgSamplerGetWrapS(wrapT) == RS_SAMPLER_CLAMP);
+ _RS_ASSERT(rsgSamplerGetWrapT(wrapT) == RS_SAMPLER_WRAP);
+ _RS_ASSERT(rsgSamplerGetAnisotropy(wrapT) == 1.0f);
+
+ _RS_ASSERT(rsgSamplerGetMagnification(anisotropy) == RS_SAMPLER_NEAREST);
+ _RS_ASSERT(rsgSamplerGetMinification(anisotropy) == RS_SAMPLER_NEAREST);
+ _RS_ASSERT(rsgSamplerGetWrapS(anisotropy) == RS_SAMPLER_CLAMP);
+ _RS_ASSERT(rsgSamplerGetWrapT(anisotropy) == RS_SAMPLER_CLAMP);
+ _RS_ASSERT(rsgSamplerGetAnisotropy(anisotropy) == 8.0f);
+
+ if (failed) {
+ rsDebug("test_sampler_getters FAILED", 0);
+ }
+ else {
+ rsDebug("test_sampler_getters PASSED", 0);
+ }
+
+ return failed;
+}
+
+void sampler_test() {
+ bool failed = false;
+ failed |= test_sampler_getters();
+
+ if (failed) {
+ rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+ }
+ else {
+ rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+ }
+}
+
diff --git a/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java b/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java
index 5f53a9b..1a2dcb9 100644
--- a/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java
+++ b/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java
@@ -19,12 +19,21 @@
import com.android.internal.os.RuntimeInit;
import android.app.ActivityManager;
+import android.app.ActivityManager.ProcessErrorStateInfo;
import android.content.Context;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.test.AndroidTestCase;
import android.util.Log;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Set;
/**
* This smoke test is designed to quickly sniff for any error conditions
@@ -32,53 +41,125 @@
*/
public class ProcessErrorsTest extends AndroidTestCase {
- private final String TAG = "ProcessErrorsTest";
+ private static final String TAG = "ProcessErrorsTest";
protected ActivityManager mActivityManager;
+ protected PackageManager mPackageManager;
@Override
public void setUp() throws Exception {
super.setUp();
- mActivityManager = (ActivityManager)
+ mActivityManager = (ActivityManager)
getContext().getSystemService(Context.ACTIVITY_SERVICE);
+ mPackageManager = getContext().getPackageManager();
}
public void testSetUpConditions() throws Exception {
assertNotNull(mActivityManager);
+ assertNotNull(mPackageManager);
}
public void testNoProcessErrors() throws Exception {
- List<ActivityManager.ProcessErrorStateInfo> errList;
+ final String reportMsg = checkForProcessErrors();
+ if (reportMsg != null) {
+ Log.w(TAG, reportMsg);
+ }
+
+ // report a non-empty list back to the test framework
+ assertNull(reportMsg, reportMsg);
+ }
+
+ private String checkForProcessErrors() throws Exception {
+ List<ProcessErrorStateInfo> errList;
errList = mActivityManager.getProcessesInErrorState();
// note: this contains information about each process that is currently in an error
// condition. if the list is empty (null) then "we're good".
// if the list is non-empty, then it's useful to report the contents of the list
- // we'll put a copy in the log, and we'll report it back to the framework via the assert.
final String reportMsg = reportListContents(errList);
- if (reportMsg != null) {
- Log.w(TAG, reportMsg);
- }
-
- // report a non-empty list back to the test framework
- assertNull(reportMsg, errList);
+ return reportMsg;
}
-
+
+ /**
+ * A test that runs all Launcher-launchable activities and verifies that no ANRs or crashes
+ * happened while doing so.
+ * <p />
+ * FIXME: Doesn't detect multiple crashing apps properly, since the crash dialog for the
+ * FIXME: first app doesn't go away.
+ */
+ public void testRunAllActivities() throws Exception {
+ final Intent home = new Intent(Intent.ACTION_MAIN);
+ home.addCategory(Intent.CATEGORY_HOME);
+ home.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ final Intent launchable = new Intent(Intent.ACTION_MAIN);
+ launchable.addCategory(Intent.CATEGORY_LAUNCHER);
+ final List<ResolveInfo> activities = mPackageManager.queryIntentActivities(launchable, 0);
+ final Set<ProcessError> errSet = new HashSet<ProcessError>();
+
+ for (ResolveInfo info : activities) {
+ Log.i(TAG, String.format("Got %s/%s", info.activityInfo.packageName,
+ info.activityInfo.name));
+
+ // build an Intent to launch the app
+ final ComponentName component = new ComponentName(info.activityInfo.packageName,
+ info.activityInfo.name);
+ final Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setComponent(component);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // launch app, and wait 7 seconds for it to start/settle
+ getContext().startActivity(intent);
+ try {
+ Thread.sleep(7000);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+
+ // See if there are any errors
+ Collection<ProcessErrorStateInfo> procs = mActivityManager.getProcessesInErrorState();
+ if (procs != null) {
+ errSet.addAll(ProcessError.fromCollection(procs));
+ }
+
+ // Send the "home" intent and wait 2 seconds for us to get there
+ getContext().startActivity(home);
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+
+ if (!errSet.isEmpty()) {
+ fail(String.format("Got %d errors: %s", errSet.size(),
+ reportWrappedListContents(errSet)));
+ }
+ }
+
+ private String reportWrappedListContents(Collection<ProcessError> errList) {
+ List<ProcessErrorStateInfo> newList = new ArrayList<ProcessErrorStateInfo>(errList.size());
+ for (ProcessError err : errList) {
+ newList.add(err.info);
+ }
+ return reportListContents(newList);
+ }
+
/**
* This helper function will dump the actual error reports.
*
* @param errList The error report containing one or more error records.
* @return Returns a string containing all of the errors.
*/
- private String reportListContents(List<ActivityManager.ProcessErrorStateInfo> errList) {
+ private String reportListContents(Collection<ProcessErrorStateInfo> errList) {
if (errList == null) return null;
StringBuilder builder = new StringBuilder();
- Iterator<ActivityManager.ProcessErrorStateInfo> iter = errList.iterator();
+ Iterator<ProcessErrorStateInfo> iter = errList.iterator();
while (iter.hasNext()) {
- ActivityManager.ProcessErrorStateInfo entry = iter.next();
+ ProcessErrorStateInfo entry = iter.next();
String condition;
switch (entry.condition) {
@@ -96,8 +177,77 @@
builder.append("Process error ").append(condition).append(" ");
builder.append(" ").append(entry.shortMsg);
builder.append(" detected in ").append(entry.processName).append(" ").append(entry.tag);
+ builder.append("\n");
}
return builder.toString();
}
-
+
+ /**
+ * A {@link ProcessErrorStateInfo} wrapper class that hashes how we want (so that equivalent
+ * crashes are considered equal).
+ */
+ private static class ProcessError {
+ public final ProcessErrorStateInfo info;
+
+ public ProcessError(ProcessErrorStateInfo newInfo) {
+ info = newInfo;
+ }
+
+ public static Collection<ProcessError> fromCollection(Collection<ProcessErrorStateInfo> in)
+ {
+ List<ProcessError> out = new ArrayList<ProcessError>(in.size());
+ for (ProcessErrorStateInfo info : in) {
+ out.add(new ProcessError(info));
+ }
+ return out;
+ }
+
+ private boolean strEquals(String a, String b) {
+ if ((a == null) && (b == null)) {
+ return true;
+ } else if ((a == null) || (b == null)) {
+ return false;
+ } else {
+ return a.equals(b);
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == null) return false;
+ if (!(other instanceof ProcessError)) return false;
+ ProcessError peOther = (ProcessError) other;
+
+ return (info.condition == peOther.info.condition)
+ && strEquals(info.longMsg, peOther.info.longMsg)
+ && (info.pid == peOther.info.pid)
+ && strEquals(info.processName, peOther.info.processName)
+ && strEquals(info.shortMsg, peOther.info.shortMsg)
+ && strEquals(info.stackTrace, peOther.info.stackTrace)
+ && strEquals(info.tag, peOther.info.tag)
+ && (info.uid == peOther.info.uid);
+ }
+
+ private int hash(Object obj) {
+ if (obj == null) {
+ return 13;
+ } else {
+ return obj.hashCode();
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ int code = 17;
+ code += info.condition;
+ code *= hash(info.longMsg);
+ code += info.pid;
+ code *= hash(info.processName);
+ code *= hash(info.shortMsg);
+ code *= hash(info.stackTrace);
+ code *= hash(info.tag);
+ code += info.uid;
+ return code;
+ }
+ }
}
diff --git a/tests/SmokeTestApps/Android.mk b/tests/SmokeTestApps/Android.mk
new file mode 100644
index 0000000..3f5f011
--- /dev/null
+++ b/tests/SmokeTestApps/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := SmokeTestTriggerApps
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/SmokeTestApps/AndroidManifest.xml b/tests/SmokeTestApps/AndroidManifest.xml
new file mode 100644
index 0000000..0f20107
--- /dev/null
+++ b/tests/SmokeTestApps/AndroidManifest.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.smoketest.triggers">
+
+ <application android:label="something">
+ <activity android:name=".CrashyApp"
+ android:label="Test Crashy App">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".CrashyApp2"
+ android:label="Test Crashy App2">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".UnresponsiveApp"
+ android:label="Test Unresponsive App">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/SmokeTestApps/README b/tests/SmokeTestApps/README
new file mode 100644
index 0000000..04aa366
--- /dev/null
+++ b/tests/SmokeTestApps/README
@@ -0,0 +1,3 @@
+The apps in this folder are intentionally bad-behaving apps that are intended
+to trigger the smoke tests to fail. They are otherwise not useful.
+
diff --git a/tests/SmokeTestApps/src/com/android/smoketest/triggers/CrashyApp.java b/tests/SmokeTestApps/src/com/android/smoketest/triggers/CrashyApp.java
new file mode 100644
index 0000000..c11b0f3
--- /dev/null
+++ b/tests/SmokeTestApps/src/com/android/smoketest/triggers/CrashyApp.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.smoketest.triggers;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class CrashyApp extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ TextView tv = new TextView(this);
+ tv.setText("Hello, Crashy Android");
+ setContentView(tv);
+ }
+
+ @Override
+ public void onResume() {
+ ((String) null).length();
+ }
+}
diff --git a/tests/SmokeTestApps/src/com/android/smoketest/triggers/CrashyApp2.java b/tests/SmokeTestApps/src/com/android/smoketest/triggers/CrashyApp2.java
new file mode 100644
index 0000000..3ef5b2b
--- /dev/null
+++ b/tests/SmokeTestApps/src/com/android/smoketest/triggers/CrashyApp2.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.smoketest.triggers;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class CrashyApp2 extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ TextView tv = new TextView(this);
+ tv.setText("Hello, Other Crashy Android");
+ setContentView(tv);
+ }
+
+
+ @Override
+ public void onResume() {
+ throw new RuntimeException("Two drums and a cymbal fall off a cliff...");
+ }
+}
diff --git a/tests/SmokeTestApps/src/com/android/smoketest/triggers/UnresponsiveApp.java b/tests/SmokeTestApps/src/com/android/smoketest/triggers/UnresponsiveApp.java
new file mode 100644
index 0000000..1291897
--- /dev/null
+++ b/tests/SmokeTestApps/src/com/android/smoketest/triggers/UnresponsiveApp.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.smoketest.triggers;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class UnresponsiveApp extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ TextView tv = new TextView(this);
+ tv.setText("Hello, Unresponsive Android");
+ setContentView(tv);
+ }
+
+ @Override
+ public void onResume() {
+ // Attempt to provoke the ire of the ActivityManager
+ while (true) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+ }
+}
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
index bbb74d1..d05e0b8 100644
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ b/wifi/java/android/net/wifi/WifiMonitor.java
@@ -366,17 +366,6 @@
handleDriverEvent(eventData);
} else if (event == TERMINATING) {
/**
- * If monitor socket is closed, we have already
- * stopped the supplicant, simply exit the monitor thread
- */
- if (eventData.startsWith(MONITOR_SOCKET_CLOSED_STR)) {
- if (false) {
- Log.d(TAG, "Monitor socket is closed, exiting thread");
- }
- break;
- }
-
- /**
* Close the supplicant connection if we see
* too many recv errors
*/
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 48a785c..e3dd3a6 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -39,6 +39,8 @@
*/
public class WifiNative {
+ private static final boolean DBG = false;
+ private final String mTAG;
private static final int DEFAULT_GROUP_OWNER_INTENT = 7;
static final int BLUETOOTH_COEXISTENCE_MODE_ENABLED = 0;
@@ -53,9 +55,7 @@
public native static boolean unloadDriver();
- public native static boolean startSupplicant();
-
- public native static boolean startP2pSupplicant();
+ public native static boolean startSupplicant(boolean p2pSupported);
/* Sends a kill signal to supplicant. To be used when we have lost connection
or when the supplicant is hung */
@@ -79,6 +79,7 @@
public WifiNative(String iface) {
mInterface = iface;
+ mTAG = "WifiNative-" + iface;
}
public boolean connectToSupplicant() {
@@ -94,14 +95,17 @@
}
private boolean doBooleanCommand(String command) {
+ if (DBG) Log.d(mTAG, "doBoolean: " + command);
return doBooleanCommand(mInterface, command);
}
private int doIntCommand(String command) {
+ if (DBG) Log.d(mTAG, "doInt: " + command);
return doIntCommand(mInterface, command);
}
private String doStringCommand(String command) {
+ if (DBG) Log.d(mTAG, "doString: " + command);
return doStringCommand(mInterface, command);
}
@@ -437,6 +441,10 @@
return doBooleanCommand("P2P_FIND " + timeout);
}
+ public boolean p2pStopFind() {
+ return doBooleanCommand("P2P_STOP_FIND");
+ }
+
public boolean p2pListen() {
return doBooleanCommand("P2P_LISTEN");
}
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index b8b7c0e..0134456 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -45,6 +45,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.DhcpInfoInternal;
@@ -118,6 +119,8 @@
private INetworkManagementService mNwService;
private ConnectivityManager mCm;
+ private final boolean mP2pSupported;
+
/* Scan results handling */
private List<ScanResult> mScanResults;
private static final Pattern scanResultPattern = Pattern.compile("\t+");
@@ -361,9 +364,9 @@
/* Reset the WPS state machine */
static final int CMD_RESET_WPS_STATE = BASE + 122;
- /* Interaction with WifiP2pService */
- public static final int WIFI_ENABLE_PENDING = BASE + 131;
- public static final int P2P_ENABLE_PROCEED = BASE + 132;
+ /* P2p commands */
+ public static final int CMD_ENABLE_P2P = BASE + 131;
+ public static final int CMD_DISABLE_P2P = BASE + 132;
private static final int CONNECT_MODE = 1;
private static final int SCAN_ONLY_MODE = 2;
@@ -482,9 +485,6 @@
/* Waiting for untether confirmation to stop soft Ap */
private State mSoftApStoppingState = new SoftApStoppingState();
- /* Wait till p2p is disabled */
- private State mWaitForP2pDisableState = new WaitForP2pDisableState();
-
private class TetherStateChange {
ArrayList<String> available;
ArrayList<String> active;
@@ -556,6 +556,9 @@
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
mNwService = INetworkManagementService.Stub.asInterface(b);
+ mP2pSupported = mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_WIFI_DIRECT);
+
mWifiNative = new WifiNative(mInterfaceName);
mWifiConfigStore = new WifiConfigStore(context, mWifiNative);
mWifiMonitor = new WifiMonitor(this, mWifiNative);
@@ -639,7 +642,6 @@
addState(mTetheringState, mSoftApStartedState);
addState(mTetheredState, mSoftApStartedState);
addState(mSoftApStoppingState, mDefaultState);
- addState(mWaitForP2pDisableState, mDefaultState);
setInitialState(mInitialState);
@@ -1625,14 +1627,14 @@
private void handleNetworkDisconnect() {
if (DBG) log("Stopping DHCP and clearing IP");
- /* In case we were in middle of DHCP operation
- restore back powermode */
- handlePostDhcpSetup();
-
/*
* stop DHCP
*/
if (mDhcpStateMachine != null) {
+ /* In case we were in middle of DHCP operation
+ restore back powermode */
+ handlePostDhcpSetup();
+
mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
mDhcpStateMachine.quit();
mDhcpStateMachine = null;
@@ -1896,11 +1898,6 @@
mReplyChannel.replyToMessage(message, WifiManager.CMD_WPS_COMPLETED,
new WpsResult(Status.FAILURE));
break;
- case WifiP2pService.P2P_ENABLE_PENDING:
- // turn off wifi and defer to be handled in DriverUnloadedState
- setWifiEnabled(false);
- deferMessage(message);
- break;
default:
loge("Error! unhandled message" + message);
break;
@@ -2060,7 +2057,7 @@
loge("Unable to change interface settings: " + ie);
}
- if(mWifiNative.startSupplicant()) {
+ if(mWifiNative.startSupplicant(mP2pSupported)) {
if (DBG) log("Supplicant start successful");
mWifiMonitor.startMonitoring();
transitionTo(mSupplicantStartingState);
@@ -2172,11 +2169,7 @@
if (DBG) log(getName() + message.toString() + "\n");
switch (message.what) {
case CMD_LOAD_DRIVER:
- mWifiP2pChannel.sendMessage(WIFI_ENABLE_PENDING);
- transitionTo(mWaitForP2pDisableState);
- break;
- case WifiP2pService.P2P_ENABLE_PENDING:
- mReplyChannel.replyToMessage(message, P2P_ENABLE_PROCEED);
+ transitionTo(mDriverLoadingState);
break;
default:
return NOT_HANDLED;
@@ -2395,6 +2388,10 @@
public void enter() {
if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+
+ /* Send any reset commands to supplicant before shutting it down */
+ handleNetworkDisconnect();
+
if (DBG) log("stopping supplicant");
if (!mWifiNative.stopSupplicant()) {
loge("Failed to stop supplicant");
@@ -2405,7 +2402,6 @@
++mSupplicantStopFailureToken, 0), SUPPLICANT_RESTART_INTERVAL_MSECS);
mNetworkInfo.setIsAvailable(false);
- handleNetworkDisconnect();
setWifiState(WIFI_STATE_DISABLING);
sendSupplicantConnectionChangedBroadcast(false);
mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
@@ -2553,13 +2549,15 @@
mWifiNative.status();
transitionTo(mDisconnectedState);
}
+
+ if (mP2pSupported) mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P);
}
@Override
public boolean processMessage(Message message) {
if (DBG) log(getName() + message.toString() + "\n");
boolean eventLoggingEnabled = true;
switch(message.what) {
- case CMD_SET_SCAN_TYPE:
+ case CMD_SET_SCAN_TYPE:
mSetScanActive = (message.arg1 == SCAN_ACTIVE);
mWifiNative.setScanMode(mSetScanActive);
break;
@@ -2672,6 +2670,8 @@
mIsRunning = false;
updateBatteryWorkSource(null);
mScanResults = null;
+
+ if (mP2pSupported) mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P);
}
}
@@ -3345,7 +3345,6 @@
case CMD_START_PACKET_FILTERING:
case CMD_STOP_PACKET_FILTERING:
case CMD_TETHER_STATE_CHANGE:
- case WifiP2pService.P2P_ENABLE_PENDING:
deferMessage(message);
break;
case WifiStateMachine.CMD_RESPONSE_AP_CONFIG:
@@ -3409,55 +3408,6 @@
transitionTo(mTetheringState);
}
break;
- case WifiP2pService.P2P_ENABLE_PENDING:
- // turn of soft Ap and defer to be handled in DriverUnloadedState
- setWifiApEnabled(null, false);
- deferMessage(message);
- break;
- default:
- return NOT_HANDLED;
- }
- EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
- return HANDLED;
- }
- }
-
- class WaitForP2pDisableState extends State {
- private int mSavedArg;
- @Override
- public void enter() {
- if (DBG) log(getName() + "\n");
- EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
-
- //Preserve the argument arg1 that has information used in DriverLoadingState
- mSavedArg = getCurrentMessage().arg1;
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) log(getName() + message.toString() + "\n");
- switch(message.what) {
- case WifiP2pService.WIFI_ENABLE_PROCEED:
- //restore argument from original message (CMD_LOAD_DRIVER)
- message.arg1 = mSavedArg;
- transitionTo(mDriverLoadingState);
- break;
- case CMD_LOAD_DRIVER:
- case CMD_UNLOAD_DRIVER:
- case CMD_START_SUPPLICANT:
- case CMD_STOP_SUPPLICANT:
- case CMD_START_AP:
- case CMD_STOP_AP:
- case CMD_START_DRIVER:
- case CMD_STOP_DRIVER:
- case CMD_SET_SCAN_MODE:
- case CMD_SET_SCAN_TYPE:
- case CMD_SET_HIGH_PERF_MODE:
- case CMD_SET_COUNTRY_CODE:
- case CMD_SET_FREQUENCY_BAND:
- case CMD_START_PACKET_FILTERING:
- case CMD_STOP_PACKET_FILTERING:
- deferMessage(message);
- break;
default:
return NOT_HANDLED;
}
@@ -3507,7 +3457,6 @@
case CMD_SET_FREQUENCY_BAND:
case CMD_START_PACKET_FILTERING:
case CMD_STOP_PACKET_FILTERING:
- case WifiP2pService.P2P_ENABLE_PENDING:
deferMessage(message);
break;
default:
@@ -3603,7 +3552,6 @@
case CMD_SET_FREQUENCY_BAND:
case CMD_START_PACKET_FILTERING:
case CMD_STOP_PACKET_FILTERING:
- case WifiP2pService.P2P_ENABLE_PENDING:
deferMessage(message);
break;
default:
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
index 7471a2d..b0cde64 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
@@ -301,7 +301,8 @@
private String trimQuotes(String str) {
str = str.trim();
if (str.startsWith("'") && str.endsWith("'")) {
- return str.substring(1, str.length()-1);
+ if (str.length() <= 2) return "";
+ else return str.substring(1, str.length()-1);
}
return str;
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 9205300..4fd0a57 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -199,68 +199,61 @@
private static final int BASE = Protocol.BASE_WIFI_P2P_MANAGER;
/** @hide */
- public static final int ENABLE_P2P = BASE + 1;
+ public static final int DISCOVER_PEERS = BASE + 1;
/** @hide */
- public static final int ENABLE_P2P_FAILED = BASE + 2;
+ public static final int DISCOVER_PEERS_FAILED = BASE + 2;
/** @hide */
- public static final int ENABLE_P2P_SUCCEEDED = BASE + 3;
+ public static final int DISCOVER_PEERS_SUCCEEDED = BASE + 3;
/** @hide */
- public static final int DISABLE_P2P = BASE + 4;
+ public static final int STOP_DISCOVERY = BASE + 4;
/** @hide */
- public static final int DISABLE_P2P_FAILED = BASE + 5;
+ public static final int STOP_DISCOVERY_FAILED = BASE + 5;
/** @hide */
- public static final int DISABLE_P2P_SUCCEEDED = BASE + 6;
+ public static final int STOP_DISCOVERY_SUCCEEDED = BASE + 6;
/** @hide */
- public static final int DISCOVER_PEERS = BASE + 7;
+ public static final int CONNECT = BASE + 7;
/** @hide */
- public static final int DISCOVER_PEERS_FAILED = BASE + 8;
+ public static final int CONNECT_FAILED = BASE + 8;
/** @hide */
- public static final int DISCOVER_PEERS_SUCCEEDED = BASE + 9;
+ public static final int CONNECT_SUCCEEDED = BASE + 9;
/** @hide */
- public static final int CONNECT = BASE + 10;
+ public static final int CANCEL_CONNECT = BASE + 10;
/** @hide */
- public static final int CONNECT_FAILED = BASE + 11;
+ public static final int CANCEL_CONNECT_FAILED = BASE + 11;
/** @hide */
- public static final int CONNECT_SUCCEEDED = BASE + 12;
+ public static final int CANCEL_CONNECT_SUCCEEDED = BASE + 12;
/** @hide */
- public static final int CANCEL_CONNECT = BASE + 13;
+ public static final int CREATE_GROUP = BASE + 13;
/** @hide */
- public static final int CANCEL_CONNECT_FAILED = BASE + 14;
+ public static final int CREATE_GROUP_FAILED = BASE + 14;
/** @hide */
- public static final int CANCEL_CONNECT_SUCCEEDED = BASE + 15;
+ public static final int CREATE_GROUP_SUCCEEDED = BASE + 15;
/** @hide */
- public static final int CREATE_GROUP = BASE + 16;
+ public static final int REMOVE_GROUP = BASE + 16;
/** @hide */
- public static final int CREATE_GROUP_FAILED = BASE + 17;
+ public static final int REMOVE_GROUP_FAILED = BASE + 17;
/** @hide */
- public static final int CREATE_GROUP_SUCCEEDED = BASE + 18;
+ public static final int REMOVE_GROUP_SUCCEEDED = BASE + 18;
/** @hide */
- public static final int REMOVE_GROUP = BASE + 19;
+ public static final int REQUEST_PEERS = BASE + 19;
/** @hide */
- public static final int REMOVE_GROUP_FAILED = BASE + 20;
- /** @hide */
- public static final int REMOVE_GROUP_SUCCEEDED = BASE + 21;
+ public static final int RESPONSE_PEERS = BASE + 20;
/** @hide */
- public static final int REQUEST_PEERS = BASE + 22;
+ public static final int REQUEST_CONNECTION_INFO = BASE + 21;
/** @hide */
- public static final int RESPONSE_PEERS = BASE + 23;
+ public static final int RESPONSE_CONNECTION_INFO = BASE + 22;
/** @hide */
- public static final int REQUEST_CONNECTION_INFO = BASE + 24;
+ public static final int REQUEST_GROUP_INFO = BASE + 23;
/** @hide */
- public static final int RESPONSE_CONNECTION_INFO = BASE + 25;
-
- /** @hide */
- public static final int REQUEST_GROUP_INFO = BASE + 26;
- /** @hide */
- public static final int RESPONSE_GROUP_INFO = BASE + 27;
+ public static final int RESPONSE_GROUP_INFO = BASE + 24;
/**
* Create a new WifiP2pManager instance. Applications use
@@ -376,6 +369,7 @@
break;
/* ActionListeners grouped together */
case WifiP2pManager.DISCOVER_PEERS_FAILED:
+ case WifiP2pManager.STOP_DISCOVERY_FAILED:
case WifiP2pManager.CONNECT_FAILED:
case WifiP2pManager.CANCEL_CONNECT_FAILED:
case WifiP2pManager.CREATE_GROUP_FAILED:
@@ -386,6 +380,7 @@
break;
/* ActionListeners grouped together */
case WifiP2pManager.DISCOVER_PEERS_SUCCEEDED:
+ case WifiP2pManager.STOP_DISCOVERY_SUCCEEDED:
case WifiP2pManager.CONNECT_SUCCEEDED:
case WifiP2pManager.CANCEL_CONNECT_SUCCEEDED:
case WifiP2pManager.CREATE_GROUP_SUCCEEDED:
@@ -459,26 +454,6 @@
}
/**
- * Sends in a request to the system to enable p2p. This will pop up a dialog
- * to the user and upon authorization will enable p2p.
- * @hide
- */
- public void enableP2p(Channel c) {
- if (c == null) return;
- c.mAsyncChannel.sendMessage(ENABLE_P2P);
- }
-
- /**
- * Sends in a request to the system to disable p2p. This will pop up a dialog
- * to the user and upon authorization will enable p2p.
- * @hide
- */
- public void disableP2p(Channel c) {
- if (c == null) return;
- c.mAsyncChannel.sendMessage(DISABLE_P2P);
- }
-
- /**
* Initiate peer discovery. A discovery process involves scanning for available Wi-Fi peers
* for the purpose of establishing a connection.
*
@@ -503,6 +478,16 @@
}
/**
+ * TODO: Add more documentation before opening up
+ * Cancel peer discovery
+ * @hide
+ */
+ public void stopPeerDiscovery(Channel c, ActionListener listener) {
+ if (c == null) return;
+ c.mAsyncChannel.sendMessage(STOP_DISCOVERY, 0, c.putListener(listener));
+ }
+
+ /**
* Start a p2p connection to a device with the specified configuration.
*
* <p> The function call immediately returns after sending a connection request
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 69cbb5c..5b0e424 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -49,6 +49,7 @@
import android.os.HandlerThread;
import android.os.Message;
import android.os.Messenger;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.provider.Settings;
@@ -84,7 +85,7 @@
*/
public class WifiP2pService extends IWifiP2pManager.Stub {
private static final String TAG = "WifiP2pService";
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
private static final String NETWORKTYPE = "WIFI_P2P";
private Context mContext;
@@ -94,11 +95,6 @@
INetworkManagementService mNwService;
private DhcpStateMachine mDhcpStateMachine;
- //Tracked to notify the user about wifi client/hotspot being shut down
- //during p2p bring up
- private int mWifiState = WifiManager.WIFI_STATE_DISABLED;
- private int mWifiApState = WifiManager.WIFI_AP_STATE_DISABLED;
-
private P2pStateMachine mP2pStateMachine;
private AsyncChannel mReplyChannel = new AsyncChannel();
private AsyncChannel mWifiChannel;
@@ -110,6 +106,9 @@
private static final int GROUP_CREATING_WAIT_TIME_MS = 120 * 1000;
private static int mGroupCreatingTimeoutIndex = 0;
+ /* Set a two minute discover timeout to avoid STA scans from being blocked */
+ private static final int DISCOVER_TIMEOUT_S = 120;
+
/**
* Delay between restarts upon failure to setup connection with supplicant
*/
@@ -124,28 +123,13 @@
private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE;
- /* Message sent to WifiStateMachine to indicate p2p enable is pending */
- public static final int P2P_ENABLE_PENDING = BASE + 1;
- /* Message sent to WifiStateMachine to indicate Wi-Fi client/hotspot operation can proceed */
- public static final int WIFI_ENABLE_PROCEED = BASE + 2;
-
/* Delayed message to timeout group creation */
- public static final int GROUP_CREATING_TIMED_OUT = BASE + 3;
-
- /* User accepted to disable Wi-Fi in order to enable p2p */
- private static final int WIFI_DISABLE_USER_ACCEPT = BASE + 4;
- /* User rejected to disable Wi-Fi in order to enable p2p */
- private static final int WIFI_DISABLE_USER_REJECT = BASE + 5;
+ public static final int GROUP_CREATING_TIMED_OUT = BASE + 1;
/* User accepted a peer request */
- private static final int PEER_CONNECTION_USER_ACCEPT = BASE + 6;
+ private static final int PEER_CONNECTION_USER_ACCEPT = BASE + 2;
/* User rejected a peer request */
- private static final int PEER_CONNECTION_USER_REJECT = BASE + 7;
-
- /* Airplane mode changed */
- private static final int AIRPLANE_MODE_CHANGED = BASE + 8;
- /* Emergency callback mode */
- private static final int EMERGENCY_CALLBACK_MODE = BASE + 9;
+ private static final int PEER_CONNECTION_USER_REJECT = BASE + 3;
private final boolean mP2pSupported;
@@ -166,7 +150,7 @@
public WifiP2pService(Context context) {
mContext = context;
- //STOPSHIP: fix this
+ //STOPSHIP: get this from native side
mInterface = "p2p0";
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORKTYPE, "");
@@ -179,15 +163,6 @@
mP2pStateMachine = new P2pStateMachine(TAG, mP2pSupported);
mP2pStateMachine.start();
-
- // broadcasts
- IntentFilter filter = new IntentFilter();
- filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
- filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
- filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
- filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
- mContext.registerReceiver(new WifiStateReceiver(), filter);
-
}
public void connectivityServiceReady() {
@@ -195,26 +170,6 @@
mNwService = INetworkManagementService.Stub.asInterface(b);
}
- private class WifiStateReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
- mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
- WifiManager.WIFI_STATE_DISABLED);
- } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
- mWifiApState = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE,
- WifiManager.WIFI_AP_STATE_DISABLED);
- } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
- mP2pStateMachine.sendMessage(AIRPLANE_MODE_CHANGED);
- } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
- if (intent.getBooleanExtra("phoneinECMState", false) == true) {
- mP2pStateMachine.sendMessage(EMERGENCY_CALLBACK_MODE);
- }
- }
- }
- }
-
private void enforceAccessPermission() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE,
"WifiP2pService");
@@ -264,8 +219,6 @@
private P2pNotSupportedState mP2pNotSupportedState = new P2pNotSupportedState();
private P2pDisablingState mP2pDisablingState = new P2pDisablingState();
private P2pDisabledState mP2pDisabledState = new P2pDisabledState();
- private WaitForUserActionState mWaitForUserActionState = new WaitForUserActionState();
- private WaitForWifiDisableState mWaitForWifiDisableState = new WaitForWifiDisableState();
private P2pEnablingState mP2pEnablingState = new P2pEnablingState();
private P2pEnabledState mP2pEnabledState = new P2pEnabledState();
// Inactive is when p2p is enabled with no connectivity
@@ -299,8 +252,6 @@
addState(mP2pNotSupportedState, mDefaultState);
addState(mP2pDisablingState, mDefaultState);
addState(mP2pDisabledState, mDefaultState);
- addState(mWaitForUserActionState, mP2pDisabledState);
- addState(mWaitForWifiDisableState, mP2pDisabledState);
addState(mP2pEnablingState, mDefaultState);
addState(mP2pEnabledState, mDefaultState);
addState(mInactiveState, mP2pEnabledState);
@@ -346,23 +297,14 @@
AsyncChannel ac = new AsyncChannel();
ac.connect(mContext, getHandler(), message.replyTo);
break;
- case WifiStateMachine.WIFI_ENABLE_PENDING:
- // Disable p2p operation before we can respond
- sendMessage(WifiP2pManager.DISABLE_P2P);
- deferMessage(message);
- break;
- case WifiP2pManager.ENABLE_P2P:
- replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED,
- WifiP2pManager.BUSY);
- break;
- case WifiP2pManager.DISABLE_P2P:
- replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED,
- WifiP2pManager.BUSY);
- break;
case WifiP2pManager.DISCOVER_PEERS:
replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
WifiP2pManager.BUSY);
break;
+ case WifiP2pManager.STOP_DISCOVERY:
+ replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED,
+ WifiP2pManager.BUSY);
+ break;
case WifiP2pManager.CONNECT:
replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
WifiP2pManager.BUSY);
@@ -388,16 +330,14 @@
case WifiP2pManager.REQUEST_GROUP_INFO:
replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, mGroup);
break;
- case AIRPLANE_MODE_CHANGED:
- if (isAirplaneModeOn()) sendMessage(WifiP2pManager.DISABLE_P2P);
- break;
- case EMERGENCY_CALLBACK_MODE:
- sendMessage(WifiP2pManager.DISABLE_P2P);
- break;
// Ignore
case WifiMonitor.P2P_INVITATION_RESULT_EVENT:
- case WIFI_DISABLE_USER_ACCEPT:
- case WIFI_DISABLE_USER_REJECT:
+ case WifiMonitor.SCAN_RESULTS_EVENT:
+ case WifiMonitor.SUP_CONNECTION_EVENT:
+ case WifiMonitor.SUP_DISCONNECTION_EVENT:
+ case WifiMonitor.NETWORK_CONNECTION_EVENT:
+ case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
+ case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
case PEER_CONNECTION_USER_ACCEPT:
case PEER_CONNECTION_USER_REJECT:
case GROUP_CREATING_TIMED_OUT:
@@ -414,22 +354,14 @@
@Override
public boolean processMessage(Message message) {
switch (message.what) {
- // Allow Wi-Fi to proceed
- case WifiStateMachine.WIFI_ENABLE_PENDING:
- replyToMessage(message, WIFI_ENABLE_PROCEED);
- break;
- case WifiP2pManager.ENABLE_P2P:
- replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.DISABLE_P2P:
- replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.DISCOVER_PEERS:
+ case WifiP2pManager.DISCOVER_PEERS:
replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
WifiP2pManager.P2P_UNSUPPORTED);
break;
+ case WifiP2pManager.STOP_DISCOVERY:
+ replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED,
+ WifiP2pManager.P2P_UNSUPPORTED);
+ break;
case WifiP2pManager.CONNECT:
replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
WifiP2pManager.P2P_UNSUPPORTED);
@@ -438,7 +370,7 @@
replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED,
WifiP2pManager.P2P_UNSUPPORTED);
break;
- case WifiP2pManager.CREATE_GROUP:
+ case WifiP2pManager.CREATE_GROUP:
replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
WifiP2pManager.P2P_UNSUPPORTED);
break;
@@ -455,26 +387,15 @@
class P2pDisablingState extends State {
@Override
- public void enter() {
- if (DBG) logd(getName());
- logd("stopping supplicant");
- if (!mWifiNative.stopSupplicant()) {
- loge("Failed to stop supplicant, issue kill");
- mWifiNative.killSupplicant();
- }
- }
-
- @Override
public boolean processMessage(Message message) {
if (DBG) logd(getName() + message.toString());
switch (message.what) {
case WifiMonitor.SUP_DISCONNECTION_EVENT:
- logd("Supplicant connection lost");
- mWifiNative.closeSupplicantConnection();
+ if (DBG) logd("p2p socket connection lost");
transitionTo(mP2pDisabledState);
break;
- case WifiP2pManager.ENABLE_P2P:
- case WifiP2pManager.DISABLE_P2P:
+ case WifiStateMachine.CMD_ENABLE_P2P:
+ case WifiStateMachine.CMD_DISABLE_P2P:
deferMessage(message);
break;
default:
@@ -484,7 +405,6 @@
}
}
-
class P2pDisabledState extends State {
@Override
public void enter() {
@@ -495,118 +415,19 @@
public boolean processMessage(Message message) {
if (DBG) logd(getName() + message.toString());
switch (message.what) {
- case WifiP2pManager.ENABLE_P2P:
- OnClickListener listener = new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- sendMessage(WIFI_DISABLE_USER_ACCEPT);
- } else {
- sendMessage(WIFI_DISABLE_USER_REJECT);
- }
- }
- };
-
- // Show a user request dialog if we know Wi-Fi client/hotspot is in operation
- if (mWifiState != WifiManager.WIFI_STATE_DISABLED ||
- mWifiApState != WifiManager.WIFI_AP_STATE_DISABLED) {
- Resources r = Resources.getSystem();
- AlertDialog dialog = new AlertDialog.Builder(mContext)
- .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
- .setMessage(r.getString(R.string.wifi_p2p_turnon_message))
- .setPositiveButton(r.getString(R.string.ok), listener)
- .setNegativeButton(r.getString(R.string.cancel), listener)
- .create();
- dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
- dialog.show();
- transitionTo(mWaitForUserActionState);
- } else {
- mWifiChannel.sendMessage(P2P_ENABLE_PENDING);
- transitionTo(mWaitForWifiDisableState);
- }
- replyToMessage(message, WifiP2pManager.ENABLE_P2P_SUCCEEDED);
- break;
- case WifiP2pManager.DISABLE_P2P:
- replyToMessage(message, WifiP2pManager.DISABLE_P2P_SUCCEEDED);
- break;
- case WifiStateMachine.WIFI_ENABLE_PENDING:
- replyToMessage(message, WIFI_ENABLE_PROCEED);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class WaitForUserActionState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- }
-
- @Override
- public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
- switch (message.what) {
- case WIFI_DISABLE_USER_ACCEPT:
- mWifiChannel.sendMessage(P2P_ENABLE_PENDING);
- transitionTo(mWaitForWifiDisableState);
- break;
- case WIFI_DISABLE_USER_REJECT:
- logd("User rejected enabling p2p");
- sendP2pStateChangedBroadcast(false);
- transitionTo(mP2pDisabledState);
- break;
- case WifiP2pManager.ENABLE_P2P:
- case WifiP2pManager.DISABLE_P2P:
- deferMessage(message);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class WaitForWifiDisableState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- }
-
- @Override
- public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
- switch (message.what) {
- case WifiStateMachine.P2P_ENABLE_PROCEED:
+ case WifiStateMachine.CMD_ENABLE_P2P:
try {
- mNwService.wifiFirmwareReload(mInterface, "P2P");
- } catch (Exception e) {
- loge("Failed to reload p2p firmware " + e);
- // continue
+ mNwService.setInterfaceUp(mInterface);
+ } catch (RemoteException re) {
+ loge("Unable to change interface settings: " + re);
+ } catch (IllegalStateException ie) {
+ loge("Unable to change interface settings: " + ie);
}
-
- //A runtime crash can leave the interface up and
- //this affects p2p when supplicant starts up.
- //Ensure interface is down before a supplicant start.
- try {
- mNwService.setInterfaceDown(mInterface);
- } catch (Exception e) {
- if (DBG) Slog.w(TAG, "Unable to bring down wlan interface: " + e);
- }
-
- if (mWifiNative.startP2pSupplicant()) {
- mWifiMonitor.startMonitoring();
- transitionTo(mP2pEnablingState);
- } else {
- notifyP2pEnableFailure();
- transitionTo(mP2pDisabledState);
- }
+ mWifiMonitor.startMonitoring();
+ transitionTo(mP2pEnablingState);
break;
- case WifiP2pManager.ENABLE_P2P:
- case WifiP2pManager.DISABLE_P2P:
- deferMessage(message);
+ case WifiStateMachine.CMD_DISABLE_P2P:
+ //Nothing to do
break;
default:
return NOT_HANDLED;
@@ -626,22 +447,15 @@
if (DBG) logd(getName() + message.toString());
switch (message.what) {
case WifiMonitor.SUP_CONNECTION_EVENT:
- logd("P2p start successful");
+ if (DBG) logd("P2p socket connection successful");
transitionTo(mInactiveState);
break;
case WifiMonitor.SUP_DISCONNECTION_EVENT:
- if (++mP2pRestartCount <= P2P_RESTART_TRIES) {
- loge("Failed to start p2p, retry");
- mWifiNative.killSupplicant();
- sendMessageDelayed(WifiP2pManager.ENABLE_P2P, P2P_RESTART_INTERVAL_MSECS);
- } else {
- loge("Failed " + mP2pRestartCount + " times to start p2p, quit ");
- mP2pRestartCount = 0;
- }
+ loge("P2p socket connection failed");
transitionTo(mP2pDisabledState);
break;
- case WifiP2pManager.ENABLE_P2P:
- case WifiP2pManager.DISABLE_P2P:
+ case WifiStateMachine.CMD_ENABLE_P2P:
+ case WifiStateMachine.CMD_DISABLE_P2P:
deferMessage(message);
break;
default:
@@ -658,30 +472,36 @@
sendP2pStateChangedBroadcast(true);
mNetworkInfo.setIsAvailable(true);
initializeP2pSettings();
- showNotification();
}
@Override
public boolean processMessage(Message message) {
if (DBG) logd(getName() + message.toString());
switch (message.what) {
- case WifiP2pManager.ENABLE_P2P:
- replyToMessage(message, WifiP2pManager.ENABLE_P2P_SUCCEEDED);
+ case WifiStateMachine.CMD_ENABLE_P2P:
+ //Nothing to do
break;
- case WifiP2pManager.DISABLE_P2P:
+ case WifiStateMachine.CMD_DISABLE_P2P:
if (mPeers.clear()) sendP2pPeersChangedBroadcast();
- replyToMessage(message, WifiP2pManager.DISABLE_P2P_SUCCEEDED);
+ mWifiNative.closeSupplicantConnection();
transitionTo(mP2pDisablingState);
break;
case WifiP2pManager.DISCOVER_PEERS:
- int timeout = message.arg1;
- if (mWifiNative.p2pFind(timeout)) {
+ if (mWifiNative.p2pFind(DISCOVER_TIMEOUT_S)) {
replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED);
} else {
replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
WifiP2pManager.ERROR);
}
break;
+ case WifiP2pManager.STOP_DISCOVERY:
+ if (mWifiNative.p2pStopFind()) {
+ replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_SUCCEEDED);
+ } else {
+ replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED,
+ WifiP2pManager.ERROR);
+ }
+ break;
case WifiMonitor.P2P_DEVICE_FOUND_EVENT:
WifiP2pDevice device = (WifiP2pDevice) message.obj;
if (mThisDevice.deviceAddress.equals(device.deviceAddress)) break;
@@ -692,15 +512,7 @@
device = (WifiP2pDevice) message.obj;
if (mPeers.remove(device)) sendP2pPeersChangedBroadcast();
break;
- case WifiMonitor.SUP_DISCONNECTION_EVENT: /* Supplicant died */
- loge("Connection lost, restart p2p");
- mWifiNative.killSupplicant();
- mWifiNative.closeSupplicantConnection();
- if (mPeers.clear()) sendP2pPeersChangedBroadcast();
- transitionTo(mP2pDisabledState);
- sendMessageDelayed(WifiP2pManager.ENABLE_P2P, P2P_RESTART_INTERVAL_MSECS);
- break;
- default:
+ default:
return NOT_HANDLED;
}
return HANDLED;
@@ -710,7 +522,6 @@
public void exit() {
sendP2pStateChangedBroadcast(false);
mNetworkInfo.setIsAvailable(false);
- clearNotification();
}
}
@@ -719,7 +530,8 @@
public void enter() {
if (DBG) logd(getName());
//Start listening every time we get inactive
- mWifiNative.p2pListen();
+ //TODO: Fix listen after driver behavior is fixed
+ //mWifiNative.p2pListen();
}
@Override
@@ -737,6 +549,8 @@
//TODO: if failure, remove config and do a regular p2pConnect()
mWifiNative.p2pReinvoke(netId, mSavedPeerConfig.deviceAddress);
} else {
+ //Stop discovery before issuing connect
+ mWifiNative.p2pStopFind();
//If peer is a GO, we do not need to send provisional discovery,
//the supplicant takes care of it.
if (isGroupOwner(mSavedPeerConfig.deviceAddress)) {
@@ -1114,7 +928,7 @@
}
// Do the regular device lost handling
return NOT_HANDLED;
- case WifiP2pManager.DISABLE_P2P:
+ case WifiStateMachine.CMD_DISABLE_P2P:
sendMessage(WifiP2pManager.REMOVE_GROUP);
deferMessage(message);
break;
@@ -1494,54 +1308,5 @@
Slog.e(TAG, s);
}
- private void showNotification() {
- NotificationManager notificationManager =
- (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- if (notificationManager == null || mNotification != null) {
- return;
- }
-
- Intent intent = new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS);
- intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
-
- PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
-
- Resources r = Resources.getSystem();
- CharSequence title = r.getText(R.string.wifi_p2p_enabled_notification_title);
- CharSequence message = r.getText(R.string.wifi_p2p_enabled_notification_message);
-
- mNotification = new Notification();
- mNotification.when = 0;
- //TODO: might change to be a seperate icon
- mNotification.icon = R.drawable.stat_sys_tether_wifi;
- mNotification.defaults &= ~Notification.DEFAULT_SOUND;
- mNotification.flags = Notification.FLAG_ONGOING_EVENT;
- mNotification.tickerText = title;
- mNotification.setLatestEventInfo(mContext, title, message, pi);
-
- notificationManager.notify(mNotification.icon, mNotification);
- }
-
- private void clearNotification() {
- NotificationManager notificationManager =
- (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- if (notificationManager != null && mNotification != null) {
- notificationManager.cancel(mNotification.icon);
- mNotification = null;
- }
- }
-
- private boolean isAirplaneSensitive() {
- String airplaneModeRadios = Settings.System.getString(mContext.getContentResolver(),
- Settings.System.AIRPLANE_MODE_RADIOS);
- return airplaneModeRadios == null
- || airplaneModeRadios.contains(Settings.System.RADIO_WIFI);
- }
-
- private boolean isAirplaneModeOn() {
- return isAirplaneSensitive() && Settings.System.getInt(mContext.getContentResolver(),
- Settings.System.AIRPLANE_MODE_ON, 0) == 1;
- }
-
}
}