add dram bandwidth measurement & random read/write

- dram bandwidth measures time taken to memcpy between 4MB buffers
  : results devideb by screen resolutions to show screen copy per sec.
- random R/W performs 4KB access randomly for a file.
  : Each access is aligned to 4KB.
- also reduce the number of repetition in SequentialUpdate as mako
  does not complete in 30 mins

Change-Id: I7ca382f9a6e6f361278ed91447e6b8dee38a7a2f
diff --git a/suite/pts/PtsBuild.mk b/suite/pts/PtsBuild.mk
index cb79956..4c3d4b2 100644
--- a/suite/pts/PtsBuild.mk
+++ b/suite/pts/PtsBuild.mk
@@ -21,7 +21,8 @@
 # New packages should be added here
 PTS_TEST_PACKAGES = \
     PtsDeviceFilePerf \
-    PtsDeviceUi
+    PtsDeviceUi \
+    PtsDeviceDram
 
 PTS_SUPPORT_PACKAGES := \
 	TestDeviceSetup
diff --git a/suite/pts/deviceTests/dram/Android.mk b/suite/pts/deviceTests/dram/Android.mk
new file mode 100644
index 0000000..dbe0ad3
--- /dev/null
+++ b/suite/pts/deviceTests/dram/Android.mk
@@ -0,0 +1,35 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := ptsutil ctsutil ctstestrunner
+
+LOCAL_JNI_SHARED_LIBRARIES := libptsdram_jni
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := PtsDeviceDram
+
+LOCAL_SDK_VERSION := 16
+
+include $(BUILD_PTS_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/suite/pts/deviceTests/dram/AndroidManifest.xml b/suite/pts/deviceTests/dram/AndroidManifest.xml
new file mode 100644
index 0000000..b3ee2f0
--- /dev/null
+++ b/suite/pts/deviceTests/dram/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?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.pts.dram">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+            android:targetPackage="com.android.pts.dram"
+            android:label="DRAM bandwidth measurement" />
+</manifest>
diff --git a/suite/pts/deviceTests/dram/jni/Android.mk b/suite/pts/deviceTests/dram/jni/Android.mk
new file mode 100644
index 0000000..a3dc698
--- /dev/null
+++ b/suite/pts/deviceTests/dram/jni/Android.mk
@@ -0,0 +1,31 @@
+# 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.
+#
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE    := libptsdram_jni
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := MemoryNativeJni.cpp
+
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
+
+LOCAL_SHARED_LIBRARIES := libnativehelper
+
+LOCAL_SDK_VERSION := 14
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/suite/pts/deviceTests/dram/jni/MemoryNativeJni.cpp b/suite/pts/deviceTests/dram/jni/MemoryNativeJni.cpp
new file mode 100644
index 0000000..4680eab
--- /dev/null
+++ b/suite/pts/deviceTests/dram/jni/MemoryNativeJni.cpp
@@ -0,0 +1,46 @@
+/*
+ * 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 <jni.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+long currentTimeMillis()
+{
+    struct timeval tv;
+    gettimeofday(&tv, (struct timezone *) NULL);
+    return (long)tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
+extern "C" JNIEXPORT jlong JNICALL Java_com_android_pts_dram_MemoryNative_runMemcpy(JNIEnv* env, jclass clazz, jint bufferSize,
+        jint repetition)
+{
+    char* src = (char*)malloc(bufferSize);
+    char* dst = (char*)malloc(bufferSize);
+    if ((src == NULL) || (dst == NULL)) {
+        env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"), "No memory");
+    }
+    memset(src, 0, bufferSize);
+    memset(dst, 0, bufferSize);
+    long start = currentTimeMillis();
+    for (int i = 0; i < repetition; i++) {
+        memcpy(dst, src, bufferSize);
+        src[bufferSize - 1] = i & 0xff;
+    }
+    long end = currentTimeMillis();
+    return end - start;
+}
diff --git a/suite/pts/deviceTests/dram/src/com/android/pts/dram/BandwidthTest.java b/suite/pts/deviceTests/dram/src/com/android/pts/dram/BandwidthTest.java
new file mode 100644
index 0000000..9c23f22
--- /dev/null
+++ b/suite/pts/deviceTests/dram/src/com/android/pts/dram/BandwidthTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.pts.dram;
+
+import android.content.Context;
+import android.graphics.Point;
+import android.util.Log;
+import android.view.WindowManager;
+
+import com.android.pts.util.PtsAndroidTestCase;
+import com.android.pts.util.ReportLog;
+import com.android.pts.util.Stat;
+
+public class BandwidthTest extends PtsAndroidTestCase {
+    private static final String TAG = "BandwidthTest";
+    private static final int BUFFER_SIZE = 4 * 1024 * 1024;
+
+
+    /* check how many screens the memcpy function can copy in a sec.
+     * Note that this does not represent the total memory bandwidth available in the system
+     * as typically CPU cannot use the whole bandwidth.
+     */
+    public void testMemcpy() {
+        final int REPETITION = 10;
+        final int REPEAT_IN_EACH_CALL = 100;
+        double[] result = new double[REPETITION];
+        for (int i = 0; i < REPETITION; i++) {
+            result[i] = MemoryNative.runMemcpy(BUFFER_SIZE, REPEAT_IN_EACH_CALL);
+        }
+        getReportLog().printArray("ms", result, false);
+        double[] mbps = ReportLog.calcRatePerSecArray(
+                (double)BUFFER_SIZE * REPEAT_IN_EACH_CALL / 1024.0 / 1024.0, result);
+        getReportLog().printArray("MB/s", mbps, true);
+        Stat.StatResult stat = Stat.getStat(mbps);
+        WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
+        Point size = new Point();
+        wm.getDefaultDisplay().getSize(size);
+        Log.i(TAG, " x " + size.x + " y " + size.y);
+        double pixels = size.x * size.y;
+        // now this represents how many times the whole screen can be copied in a sec.
+        double screensPerSecMin = stat.mMin / pixels * 1024.0 * 1024.0 / 4.0;
+        double screensPerSecAverage = stat.mAverage / pixels * 1024.0 * 1024.0 / 4.0;
+        getReportLog().printSummary("screen copies per sec", screensPerSecMin, screensPerSecAverage);
+    }
+}
diff --git a/suite/pts/deviceTests/dram/src/com/android/pts/dram/MemoryNative.java b/suite/pts/deviceTests/dram/src/com/android/pts/dram/MemoryNative.java
new file mode 100644
index 0000000..991de1e
--- /dev/null
+++ b/suite/pts/deviceTests/dram/src/com/android/pts/dram/MemoryNative.java
@@ -0,0 +1,31 @@
+/*
+ * 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.pts.dram;
+
+public class MemoryNative {
+    static {
+        System.loadLibrary("ptsdram_jni");
+    }
+    /**
+     * run memcpy for given number of repetition from a source to a destination buffers
+     * with each having the size of bufferSize.
+     * @param bufferSize
+     * @param repeatition
+     * @return time spent in copying in ms.
+     */
+    public static native long runMemcpy(int bufferSize, int repetition);
+}
diff --git a/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/FileUtil.java b/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/FileUtil.java
index 3b51630..906d831 100644
--- a/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/FileUtil.java
+++ b/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/FileUtil.java
@@ -25,6 +25,7 @@
 import java.util.Random;
 
 import com.android.pts.util.MeasureRun;
+import com.android.pts.util.SystemUtil;
 
 import android.content.Context;
 import android.util.Log;
@@ -219,4 +220,27 @@
         br.close();
         return amount;
     }
+
+    /**
+     * get file size exceeding total memory size ( 2x total memory).
+     * The size is rounded in bufferSize. And the size will be bigger than 400MB.
+     * @param context
+     * @param bufferSize
+     * @return
+     * @throws IOException
+     */
+    public static long getFileSizeExceedingMemory(Context context, int bufferSize)
+            throws IOException {
+        long freeDisk = SystemUtil.getFreeDiskSize(context);
+        long memSize = SystemUtil.getTotalMemory(context);
+        long diskSizeTarget = (2 * memSize / bufferSize) * bufferSize;
+        final long minimumDiskSize = (512L * 1024L * 1024L / bufferSize) * bufferSize;
+        if ( diskSizeTarget < minimumDiskSize ) {
+            diskSizeTarget = minimumDiskSize;
+        }
+        if (diskSizeTarget > freeDisk) {
+            throw new IOException("Free disk size " + freeDisk + " too small");
+        }
+        return diskSizeTarget;
+    }
 }
diff --git a/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/FullUpdateTest.java b/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/FullUpdateTest.java
index 6b42313..b6da646 100644
--- a/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/FullUpdateTest.java
+++ b/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/FullUpdateTest.java
@@ -70,10 +70,10 @@
                 DIR_WORK, FILE_SIZE);
         final int BUFFER_SIZE = 10 * 1024 * 1024;
         final byte[] data = FileUtil.generateRandomData(BUFFER_SIZE);
-        final int NUMBER_REPEATITION = 10;
-        double[] worsts = new double[NUMBER_REPEATITION];
-        double[] averages = new double[NUMBER_REPEATITION];
-        for (int i = 0; i < NUMBER_REPEATITION; i++) {
+        final int NUMBER_REPETITION = 10;
+        double[] worsts = new double[NUMBER_REPETITION];
+        double[] averages = new double[NUMBER_REPETITION];
+        for (int i = 0; i < NUMBER_REPETITION; i++) {
             final FileOutputStream out = new FileOutputStream(file);
             int numberRepeat = (int)(FILE_SIZE / BUFFER_SIZE);
             double[] times = MeasureTime.measure(numberRepeat, new MeasureRun() {
@@ -85,7 +85,8 @@
                 }
             });
             out.close();
-            double[] mbps = ReportLog.calcRatePerSecArray(BUFFER_SIZE / 1024 / 1024, times);
+            double[] mbps = ReportLog.calcRatePerSecArray((double)BUFFER_SIZE / 1024 / 1024,
+                    times);
             getReportLog().printArray(i + "-th round MB/s",
                     mbps, true);
             Stat.StatResult stat = Stat.getStat(mbps);
diff --git a/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/RandomRWTest.java b/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/RandomRWTest.java
new file mode 100644
index 0000000..4f8aad4
--- /dev/null
+++ b/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/RandomRWTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.pts.filesystemperf;
+
+import android.cts.util.TimeoutReq;
+import com.android.pts.util.MeasureRun;
+import com.android.pts.util.PtsAndroidTestCase;
+import com.android.pts.util.ReportLog;
+import com.android.pts.util.Stat;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.Random;
+
+
+public class RandomRWTest extends PtsAndroidTestCase {
+    private static final String DIR_RANDOM_WR = "RANDOM_WR";
+    private static final String DIR_RANDOM_RD = "RANDOM_RD";
+
+    @Override
+    protected void tearDown() throws Exception {
+        FileUtil.removeFileOrDir(getContext(), DIR_RANDOM_WR);
+        super.tearDown();
+    }
+
+
+    @TimeoutReq(minutes = 60)
+    public void testRandomRead() throws IOException {
+        final int READ_BUFFER_SIZE = 4 * 1024;
+        final long fileSize = FileUtil.getFileSizeExceedingMemory(getContext(), READ_BUFFER_SIZE);
+        File file = FileUtil.createNewFilledFile(getContext(),
+                DIR_RANDOM_RD, fileSize);
+
+        final byte[] data = FileUtil.generateRandomData(READ_BUFFER_SIZE);
+        Random random = new Random(0);
+        final int totalReadCount = (int)(fileSize / READ_BUFFER_SIZE);
+        final int[] readOffsets = new int[totalReadCount];
+        for (int i = 0; i < totalReadCount; i++) {
+            // align in buffer size
+            readOffsets[i] = (int)(random.nextFloat() * (fileSize - READ_BUFFER_SIZE)) &
+                    ~(READ_BUFFER_SIZE - 1);
+        }
+        final int runsInOneGo = 16;
+        final int readsInOneMeasure = totalReadCount / runsInOneGo;
+
+
+        final RandomAccessFile randomFile = new RandomAccessFile(file, "rw");
+        double[] rdAmount = new double[runsInOneGo];
+        double[] wrAmount = new double[runsInOneGo];
+        double[] times = FileUtil.measureIO(runsInOneGo, rdAmount, wrAmount, new MeasureRun() {
+
+            @Override
+            public void run(int i) throws IOException {
+                int start = i * readsInOneMeasure;
+                int end = (i + 1) * readsInOneMeasure;
+                for (int j = start; j < end; j++) {
+                    randomFile.seek(readOffsets[j]);
+                    randomFile.read(data);
+                }
+            }
+        });
+        randomFile.close();
+        double[] mbps = ReportLog.calcRatePerSecArray((double)fileSize / runsInOneGo / 1024 / 1024,
+                times);
+        getReportLog().printArray("MB/s",
+                mbps, true);
+        getReportLog().printArray("Rd amount", rdAmount, true);
+        Stat.StatResult stat = Stat.getStat(mbps);
+
+        getReportLog().printSummary("MB/s", stat.mMin, stat.mAverage);
+    }
+
+    // It is taking too long in tuna, and thus cannot run multiple times
+    @TimeoutReq(minutes = 60)
+    public void testRandomUpdate() throws IOException {
+        final int fileSize = 512 * 1024 * 1024;
+        File file = FileUtil.createNewFilledFile(getContext(),
+                DIR_RANDOM_WR, fileSize);
+        final int WRITE_BUFFER_SIZE = 4 * 1024;
+        final byte[] data = FileUtil.generateRandomData(WRITE_BUFFER_SIZE);
+        Random random = new Random(0);
+        final int totalWriteCount = fileSize / WRITE_BUFFER_SIZE;
+        final int[] writeOffsets = new int[totalWriteCount];
+        for (int i = 0; i < totalWriteCount; i++) {
+            writeOffsets[i] = (int)(random.nextFloat() * (fileSize - WRITE_BUFFER_SIZE)) &
+                    ~(WRITE_BUFFER_SIZE - 1);
+        }
+        final int runsInOneGo = 16;
+        final int writesInOneMeasure = totalWriteCount / runsInOneGo; // 32MB at a time
+
+
+        final RandomAccessFile randomFile = new RandomAccessFile(file, "rw");
+        double[] rdAmount = new double[runsInOneGo];
+        double[] wrAmount = new double[runsInOneGo];
+        double[] times = FileUtil.measureIO(runsInOneGo, rdAmount, wrAmount, new MeasureRun() {
+
+            @Override
+            public void run(int i) throws IOException {
+                int start = i * writesInOneMeasure;
+                int end = (i + 1) * writesInOneMeasure;
+                for (int j = start; j < end; j++) {
+                    randomFile.seek(writeOffsets[j]);
+                    randomFile.write(data);
+                }
+            }
+        });
+        randomFile.close();
+        double[] mbps = ReportLog.calcRatePerSecArray((double)fileSize / runsInOneGo / 1024 / 1024,
+                times);
+        getReportLog().printArray("MB/s",
+                mbps, true);
+        getReportLog().printArray("Wr amount", wrAmount, true);
+        Stat.StatResult stat = Stat.getStat(mbps);
+
+        getReportLog().printSummary("MB/s", stat.mMin, stat.mAverage);
+    }
+}
diff --git a/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/RWTest.java b/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/SequentialRWTest.java
similarity index 79%
rename from suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/RWTest.java
rename to suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/SequentialRWTest.java
index 1a1f357..2a750b1 100644
--- a/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/RWTest.java
+++ b/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/SequentialRWTest.java
@@ -29,7 +29,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 
-public class RWTest extends PtsAndroidTestCase {
+public class SequentialRWTest extends PtsAndroidTestCase {
     private static final String DIR_SEQ_WR = "SEQ_WR";
     private static final String DIR_SEQ_UPD = "SEQ_UPD";
     private static final String DIR_SEQ_RD = "SEQ_RD";
@@ -45,7 +45,8 @@
 
     @TimeoutReq(minutes = 30)
     public void testSingleSequentialWrite() throws IOException {
-        final int numberOfFiles = (int)(getFileSizeExceedingMemory() / BUFFER_SIZE);
+        final int numberOfFiles =(int)(FileUtil.getFileSizeExceedingMemory(
+                getContext(), BUFFER_SIZE) / BUFFER_SIZE);
         getReportLog().printValue("files", numberOfFiles);
         final byte[] data = FileUtil.generateRandomData(BUFFER_SIZE);
         final File[] files = FileUtil.createNewFiles(getContext(), DIR_SEQ_WR,
@@ -59,7 +60,7 @@
                 FileUtil.writeFile(files[i], data, false);
             }
         });
-        double[] mbps = ReportLog.calcRatePerSecArray(BUFFER_SIZE / 1024 / 1024, times);
+        double[] mbps = ReportLog.calcRatePerSecArray((double)BUFFER_SIZE / 1024 / 1024, times);
         getReportLog().printArray("try " + numberOfFiles + " files, result MB/s",
                 mbps, true);
         getReportLog().printArray("Wr amount", wrAmount, true);
@@ -67,21 +68,22 @@
         getReportLog().printSummary("MB/s", stat.mMin, stat.mAverage);
     }
 
-    @TimeoutReq(minutes = 30)
+    @TimeoutReq(minutes = 60)
     public void testSingleSequentialUpdate() throws IOException {
-        final long fileSize = getFileSizeExceedingMemory();
+        final long fileSize = FileUtil.getFileSizeExceedingMemory(getContext(), BUFFER_SIZE);
         File file = FileUtil.createNewFilledFile(getContext(),
                 DIR_SEQ_UPD, fileSize);
         final byte[] data = FileUtil.generateRandomData(BUFFER_SIZE);
-        final int NUMBER_REPEATITION = 10;
-        double[] worsts = new double[NUMBER_REPEATITION];
-        double[] averages = new double[NUMBER_REPEATITION];
-        for (int i = 0; i < NUMBER_REPEATITION; i++) {
+        final int NUMBER_REPETITION = 6;
+        double[] worsts = new double[NUMBER_REPETITION];
+        double[] averages = new double[NUMBER_REPETITION];
+        for (int i = 0; i < NUMBER_REPETITION; i++) {
             final FileOutputStream out = new FileOutputStream(file);
             int numberRepeat = (int)(fileSize / BUFFER_SIZE);
             double[] rdAmount = new double[numberRepeat];
             double[] wrAmount = new double[numberRepeat];
-            double[] times = FileUtil.measureIO(numberRepeat, rdAmount, wrAmount, new MeasureRun() {
+            double[] times = FileUtil.measureIO(numberRepeat, rdAmount, wrAmount,
+                    new MeasureRun() {
 
                 @Override
                 public void run(int i) throws IOException {
@@ -90,7 +92,8 @@
                 }
             });
             out.close();
-            double[] mbps = ReportLog.calcRatePerSecArray(BUFFER_SIZE / 1024 / 1024, times);
+            double[] mbps = ReportLog.calcRatePerSecArray((double)BUFFER_SIZE / 1024 / 1024,
+                    times);
             getReportLog().printArray(i + "-th round MB/s",
                     mbps, true);
             getReportLog().printArray("Wr amount", wrAmount, true);
@@ -105,13 +108,13 @@
 
     @TimeoutReq(minutes = 30)
     public void testSingleSequentialRead() throws IOException {
-        final long fileSize = getFileSizeExceedingMemory();
+        final long fileSize = FileUtil.getFileSizeExceedingMemory(getContext(), BUFFER_SIZE);
         long start = System.currentTimeMillis();
         final File file = FileUtil.createNewFilledFile(getContext(),
                 DIR_SEQ_RD, fileSize);
         long finish = System.currentTimeMillis();
         getReportLog().printValue("write size " + fileSize + " result MB/s",
-                ReportLog.calcRatePerSec(fileSize / 1024 / 1024, finish - start));
+                ReportLog.calcRatePerSec((double)fileSize / 1024 / 1024, finish - start));
 
         final int NUMBER_READ = 10;
 
@@ -129,20 +132,10 @@
                 in.close();
             }
         });
-        double[] mbps = ReportLog.calcRatePerSecArray(fileSize / 1024 / 1024, times);
+        double[] mbps = ReportLog.calcRatePerSecArray((double)fileSize / 1024 / 1024, times);
         getReportLog().printArray("read MB/s",
                 mbps, true);
         Stat.StatResult stat = Stat.getStat(mbps);
         getReportLog().printSummary("MB/s", stat.mMin, stat.mAverage);
     }
-
-    private long getFileSizeExceedingMemory() {
-        long freeDisk = SystemUtil.getFreeDiskSize(getContext());
-        long memSize = SystemUtil.getTotalMemory(getContext());
-        long diskSizeTarget = (2 * memSize / BUFFER_SIZE) * BUFFER_SIZE;
-        if (diskSizeTarget > freeDisk) {
-            fail("Free disk size " + freeDisk + " too small");
-        }
-        return diskSizeTarget;
-    }
 }
diff --git a/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/ReportLog.java b/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/ReportLog.java
index 0169a3b..531d2f5 100644
--- a/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/ReportLog.java
+++ b/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/ReportLog.java
@@ -80,6 +80,9 @@
     }
 
     public void throwReportToHost() throws PtsException {
+        if ((mSummary == null) && mMessages.isEmpty()) {
+            return;
+        }
         StringBuilder builder = new StringBuilder();
         builder.append(mSummary);
         builder.append(SUMMARY_SEPARATOR);
@@ -97,7 +100,7 @@
     /**
      * calculate rate per sec for given change happened during given timeInMSec.
      * timeInSec with 0 value will be changed to small value to prevent divide by zero.
-     * @param change
+     * @param change total change of quality for the given duration timeInMSec.
      * @param timeInMSec
      * @return
      */