1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.mtp;
18
19import android.app.Activity;
20import android.content.Context;
21import android.os.Bundle;
22import android.os.ParcelFileDescriptor;
23import android.os.ProxyFileDescriptorCallback;
24import android.os.storage.StorageManager;
25import android.system.ErrnoException;
26import android.system.Os;
27import android.support.test.filters.LargeTest;
28import android.support.test.InstrumentationRegistry;
29import java.io.File;
30import java.io.FileNotFoundException;
31import java.io.IOException;
32import java.util.Arrays;
33import libcore.io.IoUtils;
34import org.junit.runner.RunWith;
35import org.junit.runners.JUnit4;
36import org.junit.Test;
37
38@RunWith(JUnit4.class)
39public class AppFusePerfTest {
40    final static int SIZE = 10 * 1024 * 1024;  // 10MB
41
42    @Test
43    @LargeTest
44    public void testReadWriteFile() throws IOException {
45        final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
46        final StorageManager storageManager = context.getSystemService(StorageManager.class);
47
48        final byte[] bytes = new byte[SIZE];
49        final int SAMPLES = 100;
50        final double[] readTime = new double[SAMPLES];
51        final double[] writeTime = new double[SAMPLES];
52
53        for (int i = 0; i < SAMPLES; i++) {
54            final ParcelFileDescriptor fd = storageManager.openProxyFileDescriptor(
55                    ParcelFileDescriptor.MODE_READ_ONLY, new TestCallback());
56            try (final ParcelFileDescriptor.AutoCloseInputStream stream =
57                    new ParcelFileDescriptor.AutoCloseInputStream(fd)) {
58                final long startTime = System.nanoTime();
59                stream.read(bytes);
60                readTime[i] = (System.nanoTime() - startTime) / 1000.0 / 1000.0;
61            }
62        }
63
64        for (int i = 0; i < SAMPLES; i++) {
65            final ParcelFileDescriptor fd = storageManager.openProxyFileDescriptor(
66                    ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_TRUNCATE,
67                    new TestCallback());
68            try (final ParcelFileDescriptor.AutoCloseOutputStream stream =
69                    new ParcelFileDescriptor.AutoCloseOutputStream(fd)) {
70                final long startTime = System.nanoTime();
71                stream.write(bytes);
72                writeTime[i] = (System.nanoTime() - startTime) / 1000.0 / 1000.0;
73            }
74        }
75
76        double readAverage = 0;
77        double writeAverage = 0;
78        double readSquaredAverage = 0;
79        double writeSquaredAverage = 0;
80        for (int i = 0; i < SAMPLES; i++) {
81            readAverage += readTime[i];
82            writeAverage += writeTime[i];
83            readSquaredAverage += readTime[i] * readTime[i];
84            writeSquaredAverage += writeTime[i] * writeTime[i];
85        }
86
87        readAverage /= SAMPLES;
88        writeAverage /= SAMPLES;
89        readSquaredAverage /= SAMPLES;
90        writeSquaredAverage /= SAMPLES;
91
92        final Bundle results = new Bundle();
93        results.putDouble("readAverage", readAverage);
94        results.putDouble("readStandardDeviation",
95                Math.sqrt(readSquaredAverage - readAverage * readAverage));
96        results.putDouble("writeAverage", writeAverage);
97        results.putDouble("writeStandardDeviation",
98                Math.sqrt(writeSquaredAverage - writeAverage * writeAverage));
99        InstrumentationRegistry.getInstrumentation().sendStatus(Activity.RESULT_OK, results);
100    }
101
102    private static class TestCallback extends ProxyFileDescriptorCallback {
103        @Override
104        public long onGetSize() throws ErrnoException {
105            return SIZE;
106        }
107
108        @Override
109        public int onRead(long offset, int size, byte[] data) throws ErrnoException {
110            return size;
111        }
112
113        @Override
114        public int onWrite(long offset, int size, byte[] data) throws ErrnoException {
115            return size;
116        }
117
118        @Override
119        public void onFsync() throws ErrnoException {}
120
121        @Override
122        public void onRelease() {}
123    }
124}
125