Bug 731637 - robocop on tegras hit OOM for PixelTest due to getPaintedSurface() array creation. r=kats

This commit is contained in:
Joel Maher 2012-03-06 15:08:45 -05:00
parent 4c669c07d8
commit bb58eabcf0
10 changed files with 116 additions and 31 deletions

View File

@ -77,5 +77,5 @@ public interface Driver {
* @return A 2-D array of pixels (indexed by y, then x). The pixels
* are in ARGB-8888 format.
*/
int[][] getPaintedSurface();
PaintedSurface getPaintedSurface();
}

View File

@ -48,6 +48,8 @@ import java.io.IOException;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.List;
import java.io.FileOutputStream;
import java.io.DataOutputStream;
import java.lang.Class;
import java.lang.reflect.InvocationTargetException;
@ -291,7 +293,7 @@ public class FennecNativeDriver implements Driver {
return null;
}
public int[][] getPaintedSurface() {
public PaintedSurface getPaintedSurface() {
GLSurfaceView view = getSurfaceView();
if (view == null) {
return null;
@ -309,14 +311,34 @@ public class FennecNativeDriver implements Driver {
int w = view.getWidth();
int h = view.getHeight();
pixelBuffer.position(0);
int[][] pixels = new int[h][w];
for (int y = h - 1; y >= 0; y--) {
for (int x = 0; x < w; x++) {
int agbr = pixelBuffer.get();
pixels[y][x] = (agbr & 0xFF00FF00) | ((agbr >> 16) & 0x000000FF) | ((agbr << 16) & 0x00FF0000);
String mapFile = "/mnt/sdcard/pixels.map";
FileOutputStream fos = null;
DataOutputStream dos = null;
try {
fos = new FileOutputStream(mapFile);
dos = new DataOutputStream(fos);
for (int y = h - 1; y >= 0; y--) {
for (int x = 0; x < w; x++) {
int agbr = pixelBuffer.get();
dos.writeInt((agbr & 0xFF00FF00) | ((agbr >> 16) & 0x000000FF) | ((agbr << 16) & 0x00FF0000));
}
}
return new PaintedSurface(mapFile, w, h);
} catch (IOException e) {
throw new RoboCopException("exception with pixel writer on file: " + mapFile);
} finally {
try {
if (dos != null && fos != null) {
dos.flush();
dos.close();
fos.close();
}
} catch (IOException e) {
throw new RoboCopException("exception closing pixel writer on file: " + mapFile);
}
}
return pixels;
}
public int mHeight=0;

View File

@ -61,6 +61,7 @@ _JAVA_HARNESS = \
FennecNativeDriver.java \
FennecNativeElement.java \
RoboCopException.java \
PaintedSurface.java \
$(NULL)
_JAVA_TESTS = $(patsubst $(TESTPATH)/%.in,%,$(wildcard $(TESTPATH)/*.java.in))

View File

@ -0,0 +1,62 @@
#filter substitution
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
package @ANDROID_PACKAGE_NAME@;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class PaintedSurface {
private String mFileName = null;
private int mWidth = -1;
private int mHeight = -1;
private MappedByteBuffer mPixelBuffer = null;
public PaintedSurface(String filename, int width, int height) {
mFileName = filename;
mWidth = width;
mHeight = height;
try {
File f = new File(filename);
int pixelSize = (int)f.length();
FileInputStream pixelFile = new FileInputStream(filename);
mPixelBuffer = pixelFile.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, pixelSize);
} catch (java.io.FileNotFoundException e) {
e.printStackTrace();
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
public final int getPixelAt(int x, int y) {
if (mPixelBuffer == null) {
throw new RoboCopException("Trying to access PaintedSurface with no active PixelBuffer");
}
if (x >= mWidth || x < 0) {
throw new RoboCopException("Trying to access PaintedSurface with invalid x value");
}
if (y >= mHeight || y < 0) {
throw new RoboCopException("Trying to access PaintedSurface with invalid y value");
}
// The rows are reversed so row 0 is at the end and we start with the last row.
// This is why we do mHeight-y;
int index = (x + ((mHeight - y - 1) * mWidth)) * 4;
int b1 = mPixelBuffer.get(index) & 0xFF;
int b2 = mPixelBuffer.get(index + 1) & 0xFF;
int b3 = mPixelBuffer.get(index + 2) & 0xFF;
int b4 = mPixelBuffer.get(index + 3) & 0xFF;
int value = (b1 << 24) + (b2 << 16) + (b3 << 8) + (b4 << 0);
return value;
}
}

View File

@ -6,19 +6,19 @@ import @ANDROID_PACKAGE_NAME@.*;
class PixelTest extends BaseTest {
private static final long PAINT_CLEAR_DELAY = 500; // milliseconds
protected final int[][] loadAndPaint(String url) {
protected final PaintedSurface loadAndPaint(String url) {
Actions.RepeatedEventExpecter paintExpecter = mActions.expectPaint();
loadUrl(url);
paintExpecter.blockUntilClear(PAINT_CLEAR_DELAY);
return mDriver.getPaintedSurface();
}
protected final int[][] waitForPaint(Actions.RepeatedEventExpecter expecter) {
protected final PaintedSurface waitForPaint(Actions.RepeatedEventExpecter expecter) {
expecter.blockUntilClear(PAINT_CLEAR_DELAY);
return mDriver.getPaintedSurface();
}
protected final int[][] waitWithNoPaint(Actions.RepeatedEventExpecter expecter) {
protected final PaintedSurface waitWithNoPaint(Actions.RepeatedEventExpecter expecter) {
try {
Thread.sleep(PAINT_CLEAR_DELAY);
} catch (InterruptedException ie) {
@ -41,15 +41,15 @@ class PixelTest extends BaseTest {
/**
* Checks the top-left corner of the visible area of the page is at (x,y) of robocop_boxes.html.
*/
protected final void checkScrollWithBoxes(int[][] painted, int x, int y) {
protected final void checkScrollWithBoxes(PaintedSurface painted, int x, int y) {
int[] color = getBoxColorAt(x, y);
mAsserter.ispixel(painted[0][0], color[0], color[1], color[2], "Pixel at 0, 0");
mAsserter.ispixel(painted.getPixelAt(0, 0), color[0], color[1], color[2], "Pixel at 0, 0");
color = getBoxColorAt(x + 100, y);
mAsserter.ispixel(painted[0][100], color[0], color[1], color[2], "Pixel at 100, 0");
mAsserter.ispixel(painted.getPixelAt(100, 0), color[0], color[1], color[2], "Pixel at 100, 0");
color = getBoxColorAt(x, y + 100);
mAsserter.ispixel(painted[100][0], color[0], color[1], color[2], "Pixel at 0, 100");
mAsserter.ispixel(painted.getPixelAt(0, 100), color[0], color[1], color[2], "Pixel at 0, 100");
color = getBoxColorAt(x + 100, y + 100);
mAsserter.ispixel(painted[100][100], color[0], color[1], color[2], "Pixel at 100, 100");
mAsserter.ispixel(painted.getPixelAt(100, 100), color[0], color[1], color[2], "Pixel at 100, 100");
}
/**
@ -57,8 +57,8 @@ class PixelTest extends BaseTest {
* @param url URL of the robocop_boxes.html file.
* @return The painted surface after rendering the file.
*/
protected final int[][] loadAndVerifyBoxes(String url) {
int[][] painted = loadAndPaint(url);
protected final PaintedSurface loadAndVerifyBoxes(String url) {
PaintedSurface painted = loadAndPaint(url);
checkScrollWithBoxes(painted, 0, 0);
return painted;
}

View File

@ -28,12 +28,12 @@ public class testAxisLocking extends PixelTest {
// axis locking prevents any horizontal scrolling
Actions.RepeatedEventExpecter paintExpecter = mActions.expectPaint();
meh.dragSync(20, 150, 10, 50);
int[][] painted = waitForPaint(paintExpecter);
PaintedSurface painted = waitForPaint(paintExpecter);
checkScrollWithBoxes(painted, 0, 100);
// since checkScrollWithBoxes only checks 4 points, it may not pick up a
// sub-100 pixel horizontal shift. so we check another point manually to make sure.
int[] color = getBoxColorAt(0, 100);
mAsserter.ispixel(painted[0][99], color[0], color[1], color[2], "Pixel at 99, 0 indicates no horizontal scroll");
mAsserter.ispixel(painted.getPixelAt(99, 0), color[0], color[1], color[2], "Pixel at 99, 0 indicates no horizontal scroll");
// now drag at a 45-degree angle to ensure we break the axis lock, and
// verify that we have both horizontal and vertical scrolling

View File

@ -27,7 +27,7 @@ public class testFlingCorrectness extends PixelTest {
Actions.RepeatedEventExpecter paintExpecter = mActions.expectPaint();
meh.dragSync(10, 150, 10, 50);
meh.dragSync(10, 150, 10, 50);
int[][] painted = waitForPaint(paintExpecter);
PaintedSurface painted = waitForPaint(paintExpecter);
checkScrollWithBoxes(painted, 0, 200);
// now fling page downwards using a 100-pixel drag but a velocity of 15px/sec, so that

View File

@ -28,7 +28,7 @@ public class testOverscroll extends PixelTest {
// and back this should NOT trigger a gecko-paint
Actions.RepeatedEventExpecter paintExpecter = mActions.expectPaint();
meh.dragSync(10, 50, 10, 150);
int[][] painted = waitWithNoPaint(paintExpecter);
PaintedSurface painted = waitWithNoPaint(paintExpecter);
checkScrollWithBoxes(painted, 0, 0);
// drag page rightwards to go into overscroll on the left. let it bounce and verify.

View File

@ -25,7 +25,7 @@ public class testPanCorrectness extends PixelTest {
// drag page upwards by 100 pixels
Actions.RepeatedEventExpecter paintExpecter = mActions.expectPaint();
meh.dragSync(10, 150, 10, 50);
int[][] painted = waitForPaint(paintExpecter);
PaintedSurface painted = waitForPaint(paintExpecter);
checkScrollWithBoxes(painted, 0, 100);
// drag page leftwards by 100 pixels

View File

@ -24,10 +24,10 @@ public class test_bug720538 extends PixelTest {
* the gray shades of the checkerboard.
*/
int[][] painted = loadAndPaint(url);
PaintedSurface painted = loadAndPaint(url);
// first we check that the point we want to double-tap (100, 100) is blue, indicating it's inside the iframe
mAsserter.ispixel(painted[100][100], 0, 0, 0xFF, "Ensuring double-tap point is in the iframe");
mAsserter.ispixel(painted.getPixelAt(100, 100), 0, 0, 0xFF, "Ensuring double-tap point is in the iframe");
// do the double tap and wait for the double-tap animation to finish. we assume the animation is done
// when we find a 500ms period with no paint events that occurs after at least one paint event.
@ -39,10 +39,10 @@ public class test_bug720538 extends PixelTest {
// check a few points to ensure that we did a good zoom-to-block on the iframe. this checks that
// the background color is visible on the left and right edges of the viewport, but the iframe is
// visible in between those edges
mAsserter.ispixel(painted[100][0], 0, 0x80, 0, "Checking page background to the left of the iframe");
mAsserter.ispixel(painted[100][50], 0, 0, 0xFF, "Checking for iframe a few pixels from the left edge");
mAsserter.ispixel(painted[100][mDriver.getGeckoWidth() - 51], 0, 0, 0xFF, "Checking for iframe a few pixels from the right edge");
mAsserter.ispixel(painted[100][mDriver.getGeckoWidth() - 1], 0, 0x80, 0, "Checking page background the right of the iframe");
mAsserter.ispixel(painted.getPixelAt(0, 100), 0, 0x80, 0, "Checking page background to the left of the iframe");
mAsserter.ispixel(painted.getPixelAt(50, 100), 0, 0, 0xFF, "Checking for iframe a few pixels from the left edge");
mAsserter.ispixel(painted.getPixelAt(mDriver.getGeckoWidth() - 51, 100), 0, 0, 0xFF, "Checking for iframe a few pixels from the right edge");
mAsserter.ispixel(painted.getPixelAt(mDriver.getGeckoWidth() - 1, 100), 0, 0x80, 0, "Checking page background the right of the iframe");
// now we do double-tap again to zoom out and wait for the animation to finish, as before
paintExpecter = mActions.expectPaint();
@ -54,9 +54,9 @@ public class test_bug720538 extends PixelTest {
// the last row because the last row is subject to rounding and clipping errors
for (int y = 2; y < 10; y++) {
for (int x = 0; x < 10; x++) {
mAsserter.dumpLog("Pixel at " + x + ", " + (mDriver.getGeckoHeight() - y) + ": " + Integer.toHexString(painted[mDriver.getGeckoHeight() - y][x]));
mAsserter.dumpLog("Pixel at " + x + ", " + (mDriver.getGeckoHeight() - y) + ": " + Integer.toHexString(painted.getPixelAt(x, mDriver.getGeckoHeight() - y)));
}
}
mAsserter.ispixel(painted[mDriver.getGeckoHeight() - 2][0], 0, 0x80, 0, "Checking bottom-left corner of viewport");
mAsserter.ispixel(painted.getPixelAt(0, mDriver.getGeckoHeight() - 2), 0, 0x80, 0, "Checking bottom-left corner of viewport");
}
}