diff options
4 files changed, 218 insertions, 35 deletions
diff --git a/packages/DocumentsUI/perf-tests/Android.mk b/packages/DocumentsUI/perf-tests/Android.mk index 11c163bdfbcd..919fc560951b 100644 --- a/packages/DocumentsUI/perf-tests/Android.mk +++ b/packages/DocumentsUI/perf-tests/Android.mk @@ -11,7 +11,7 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) \ ../tests/src/com/android/documentsui/StubProvider.java LOCAL_JAVA_LIBRARIES := android-support-v4 android.test.runner -LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ub-uiautomator +LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ub-uiautomator ub-janktesthelper LOCAL_PACKAGE_NAME := DocumentsUIPerfTests LOCAL_INSTRUMENTATION_FOR := DocumentsUI diff --git a/packages/DocumentsUI/perf-tests/src/com/android/documentsui/FilesJankPerfTest.java b/packages/DocumentsUI/perf-tests/src/com/android/documentsui/FilesJankPerfTest.java new file mode 100644 index 000000000000..cb2d904c9a9c --- /dev/null +++ b/packages/DocumentsUI/perf-tests/src/com/android/documentsui/FilesJankPerfTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2016 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.documentsui; + +import static com.android.documentsui.StressProvider.DEFAULT_AUTHORITY; +import static com.android.documentsui.StressProvider.STRESS_ROOT_0_ID; +import static com.android.documentsui.StressProvider.STRESS_ROOT_2_ID; + +import android.app.Activity; +import android.os.RemoteException; +import android.test.suitebuilder.annotation.LargeTest; + +import android.content.Intent; +import android.content.Context; +import android.support.test.jank.JankTest; +import android.support.test.jank.JankTestBase; +import android.support.test.uiautomator.UiDevice; +import android.support.test.jank.GfxMonitor; +import android.support.test.uiautomator.UiScrollable; +import android.util.Log; + +import com.android.documentsui.FilesActivity; +import com.android.documentsui.bots.RootsListBot; +import com.android.documentsui.bots.DirectoryListBot; + +@LargeTest +public class FilesJankPerfTest extends JankTestBase { + private static final String DOCUMENTSUI_PACKAGE = "com.android.documentsui"; + private static final int MAX_FLINGS = 10; + private static final int BOT_TIMEOUT = 5000; + + private RootsListBot mRootsListBot; + private DirectoryListBot mDirListBot; + private Activity mActivity = null; + + public void setUpInLoop() { + final UiDevice device = UiDevice.getInstance(getInstrumentation()); + final Context context = getInstrumentation().getTargetContext(); + mRootsListBot = new RootsListBot(device, context, BOT_TIMEOUT); + mDirListBot = new DirectoryListBot(device, context, BOT_TIMEOUT); + + final Intent intent = new Intent(context, FilesActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mActivity = getInstrumentation().startActivitySync(intent); + } + + public void tearDownInLoop() { + if (mActivity != null) { + mActivity.finish(); + mActivity = null; + } + } + + public void setupAndOpenInLoop() throws Exception { + setUpInLoop(); + openRoot(); + } + + public void openRoot() throws Exception { + mRootsListBot.openRoot(STRESS_ROOT_2_ID); + } + + @JankTest(expectedFrames=0, beforeLoop="setUpInLoop", afterLoop="tearDownInLoop") + @GfxMonitor(processName=DOCUMENTSUI_PACKAGE) + public void testOpenRootJankPerformance() throws Exception { + openRoot(); + getInstrumentation().waitForIdleSync(); + } + + @JankTest(expectedFrames=0, beforeLoop="setupAndOpenInLoop", afterLoop="tearDownInLoop") + @GfxMonitor(processName=DOCUMENTSUI_PACKAGE) + public void testFlingJankPerformance() throws Exception { + new UiScrollable(mDirListBot.findDocumentsList().getSelector()).flingToEnd(MAX_FLINGS); + getInstrumentation().waitForIdleSync(); + } +} diff --git a/packages/DocumentsUI/perf-tests/src/com/android/documentsui/StressProvider.java b/packages/DocumentsUI/perf-tests/src/com/android/documentsui/StressProvider.java index 1bc802a00ec6..6147a7187de7 100644 --- a/packages/DocumentsUI/perf-tests/src/com/android/documentsui/StressProvider.java +++ b/packages/DocumentsUI/perf-tests/src/com/android/documentsui/StressProvider.java @@ -32,7 +32,9 @@ import android.provider.DocumentsProvider; import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Random; /** @@ -46,11 +48,21 @@ public class StressProvider extends DocumentsProvider { // Empty root. public static final String STRESS_ROOT_0_ID = "STRESS_ROOT_0"; - // Root with thousands of items. + // Root with thousands of directories. public static final String STRESS_ROOT_1_ID = "STRESS_ROOT_1"; + // Root with hundreds of files. + public static final String STRESS_ROOT_2_ID = "STRESS_ROOT_2"; + private static final String STRESS_ROOT_0_DOC_ID = "STRESS_ROOT_0_DOC"; private static final String STRESS_ROOT_1_DOC_ID = "STRESS_ROOT_1_DOC"; + private static final String STRESS_ROOT_2_DOC_ID = "STRESS_ROOT_2_DOC"; + + private static final int STRESS_ROOT_1_ITEMS = 10000; + private static final int STRESS_ROOT_2_ITEMS = 300; + + private static final String MIME_TYPE_IMAGE = "image/jpeg"; + private static final long REFERENCE_TIMESTAMP = 1459159369359L; private static final String[] DEFAULT_ROOT_PROJECTION = new String[] { Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_TITLE, Root.COLUMN_DOCUMENT_ID, @@ -62,7 +74,12 @@ public class StressProvider extends DocumentsProvider { }; private String mAuthority = DEFAULT_AUTHORITY; - private ArrayList<String> mIds = new ArrayList<>(); + + // Map from a root document id to children document ids. + private Map<String, ArrayList<StubDocument>> mChildDocuments = new HashMap<>(); + + private Map<String, StubDocument> mDocuments = new HashMap<>(); + private Map<String, StubRoot> mRoots = new HashMap<>(); @Override public void attachInfo(Context context, ProviderInfo info) { @@ -72,20 +89,41 @@ public class StressProvider extends DocumentsProvider { @Override public boolean onCreate() { - mIds = new ArrayList(); - for (int i = 0; i < 10000; i++) { - mIds.add(createRandomId(i)); + StubDocument document; + + ArrayList<StubDocument> children = new ArrayList<StubDocument>(); + mChildDocuments.put(STRESS_ROOT_1_DOC_ID, children); + for (int i = 0; i < STRESS_ROOT_1_ITEMS; i++) { + document = StubDocument.createDirectory(i); + mDocuments.put(document.id, document); + children.add(document); + } + + children = new ArrayList<StubDocument>(); + mChildDocuments.put(STRESS_ROOT_2_DOC_ID, children); + for (int i = 0; i < STRESS_ROOT_2_ITEMS; i++) { + document = StubDocument.createFile(STRESS_ROOT_1_ITEMS + i); + mDocuments.put(document.id, document); + children.add(document); } - mIds.add(STRESS_ROOT_0_DOC_ID); - mIds.add(STRESS_ROOT_1_DOC_ID); + + mRoots.put(STRESS_ROOT_0_ID, new StubRoot(STRESS_ROOT_0_ID, STRESS_ROOT_0_DOC_ID)); + mRoots.put(STRESS_ROOT_1_ID, new StubRoot(STRESS_ROOT_1_ID, STRESS_ROOT_1_DOC_ID)); + mRoots.put(STRESS_ROOT_2_ID, new StubRoot(STRESS_ROOT_2_ID, STRESS_ROOT_2_DOC_ID)); + + mDocuments.put(STRESS_ROOT_0_DOC_ID, StubDocument.createDirectory(STRESS_ROOT_0_DOC_ID)); + mDocuments.put(STRESS_ROOT_1_DOC_ID, StubDocument.createDirectory(STRESS_ROOT_1_DOC_ID)); + mDocuments.put(STRESS_ROOT_2_DOC_ID, StubDocument.createDirectory(STRESS_ROOT_2_DOC_ID)); + return true; } @Override public Cursor queryRoots(String[] projection) throws FileNotFoundException { final MatrixCursor result = new MatrixCursor(DEFAULT_ROOT_PROJECTION); - includeRoot(result, STRESS_ROOT_0_ID, STRESS_ROOT_0_DOC_ID); - includeRoot(result, STRESS_ROOT_1_ID, STRESS_ROOT_1_DOC_ID); + for (StubRoot root : mRoots.values()) { + includeRoot(result, root); + } return result; } @@ -93,57 +131,112 @@ public class StressProvider extends DocumentsProvider { public Cursor queryDocument(String documentId, String[] projection) throws FileNotFoundException { final MatrixCursor result = new MatrixCursor(DEFAULT_DOCUMENT_PROJECTION); - includeDocument(result, documentId); + final StubDocument document = mDocuments.get(documentId); + includeDocument(result, document); return result; } @Override - public Cursor queryChildDocuments(String parentDocumentId, String[] projection, String sortOrder) + public Cursor queryChildDocuments(String parentDocumentId, String[] projection, + String sortOrder) throws FileNotFoundException { final MatrixCursor result = new MatrixCursor(DEFAULT_DOCUMENT_PROJECTION); - if (STRESS_ROOT_1_DOC_ID.equals(parentDocumentId)) { - for (String id : mIds) { - includeDocument(result, id); + final ArrayList<StubDocument> childDocuments = mChildDocuments.get(parentDocumentId); + if (childDocuments != null) { + for (StubDocument document : childDocuments) { + includeDocument(result, document); } } return result; } @Override - public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal) + public ParcelFileDescriptor openDocument(String docId, String mode, + CancellationSignal signal) throws FileNotFoundException { throw new UnsupportedOperationException(); } - private void includeRoot(MatrixCursor result, String rootId, String docId) { + private void includeRoot(MatrixCursor result, StubRoot root) { final RowBuilder row = result.newRow(); - row.add(Root.COLUMN_ROOT_ID, rootId); + row.add(Root.COLUMN_ROOT_ID, root.id); row.add(Root.COLUMN_FLAGS, 0); - row.add(Root.COLUMN_TITLE, rootId); - row.add(Root.COLUMN_DOCUMENT_ID, docId); + row.add(Root.COLUMN_TITLE, root.id); + row.add(Root.COLUMN_DOCUMENT_ID, root.documentId); } - private void includeDocument(MatrixCursor result, String id) { + private void includeDocument(MatrixCursor result, StubDocument document) { final RowBuilder row = result.newRow(); - row.add(Document.COLUMN_DOCUMENT_ID, id); - row.add(Document.COLUMN_DISPLAY_NAME, id); - row.add(Document.COLUMN_SIZE, 0); - row.add(Document.COLUMN_MIME_TYPE, DocumentsContract.Document.MIME_TYPE_DIR); + row.add(Document.COLUMN_DOCUMENT_ID, document.id); + row.add(Document.COLUMN_DISPLAY_NAME, document.id); + row.add(Document.COLUMN_SIZE, document.size); + row.add(Document.COLUMN_MIME_TYPE, document.mimeType); row.add(Document.COLUMN_FLAGS, 0); - row.add(Document.COLUMN_LAST_MODIFIED, null); + row.add(Document.COLUMN_LAST_MODIFIED, document.lastModified); } - private static String getDocumentIdForFile(File file) { + private static String getStubDocumentIdForFile(File file) { return file.getAbsolutePath(); } - private String createRandomId(int index) { - final Random random = new Random(index); - final StringBuilder builder = new StringBuilder(); - for (int i = 0; i < 20; i++) { - builder.append((char) (random.nextInt(96) + 32)); + private static class StubDocument { + final String mimeType; + final String id; + final int size; + final long lastModified; + + private StubDocument(String mimeType, String id, int size, long lastModified) { + this.mimeType = mimeType; + this.id = id; + this.size = size; + this.lastModified = lastModified; + } + + public static StubDocument createDirectory(int index) { + return new StubDocument( + DocumentsContract.Document.MIME_TYPE_DIR, createRandomId(index), 0, + createRandomTime(index)); + } + + public static StubDocument createDirectory(String id) { + return new StubDocument(DocumentsContract.Document.MIME_TYPE_DIR, id, 0, 0); + } + + public static StubDocument createFile(int index) { + return new StubDocument( + MIME_TYPE_IMAGE, createRandomId(index), createRandomSize(index), + createRandomTime(index)); + } + + private static String createRandomId(int index) { + final Random random = new Random(index); + final StringBuilder builder = new StringBuilder(); + for (int i = 0; i < 20; i++) { + builder.append((char) (random.nextInt(96) + 32)); + } + builder.append(index); // Append a number to guarantee uniqueness. + return builder.toString(); + } + + private static int createRandomSize(int index) { + final Random random = new Random(index); + return random.nextInt(1024 * 1024 * 100); // Up to 100 MB. + } + + private static long createRandomTime(int index) { + final Random random = new Random(index); + // Up to 30 days backwards from REFERENCE_TIMESTAMP. + return REFERENCE_TIMESTAMP - random.nextLong() % 1000L * 60 * 60 * 24 * 30; + } + } + + private static class StubRoot { + final String id; + final String documentId; + + public StubRoot(String id, String documentId) { + this.id = id; + this.documentId = documentId; } - builder.append(index); // Append a number to guarantee uniqueness. - return builder.toString(); } } diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/DirectoryListBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/DirectoryListBot.java index da9f9c30261a..7c1e2196f6d5 100644 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/DirectoryListBot.java +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/DirectoryListBot.java @@ -167,7 +167,7 @@ public class DirectoryListBot extends BaseBot { return true; } - private UiObject findDocumentsList() { + public UiObject findDocumentsList() { return findObject( "com.android.documentsui:id/container_directory", DIR_LIST_ID); |