Loading packages/DocumentsUI/perf-tests/Android.mk 0 → 100644 +22 −0 Original line number Diff line number Diff line LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests #LOCAL_SDK_VERSION := current LOCAL_SRC_FILES := $(call all-java-files-under, src) \ $(call all-java-files-under, ../tests/src/com/android/documentsui/bots) \ ../tests/src/com/android/documentsui/ActivityTest.java \ ../tests/src/com/android/documentsui/DocumentsProviderHelper.java \ ../tests/src/com/android/documentsui/StubProvider.java LOCAL_JAVA_LIBRARIES := android.test.runner LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 mockito-target ub-uiautomator LOCAL_PACKAGE_NAME := DocumentsUIPerfTests LOCAL_INSTRUMENTATION_FOR := DocumentsUI LOCAL_CERTIFICATE := platform include $(BUILD_PACKAGE) packages/DocumentsUI/perf-tests/AndroidManifest.xml 0 → 100644 +24 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.documentsui.perftests"> <application> <uses-library android:name="android.test.runner" /> <provider android:name="com.android.documentsui.StressProvider" android:authorities="com.android.documentsui.stressprovider" android:exported="true" android:grantUriPermissions="true" android:permission="android.permission.MANAGE_DOCUMENTS" android:enabled="true"> <intent-filter> <action android:name="android.content.action.DOCUMENTS_PROVIDER" /> </intent-filter> </provider> </application> <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.android.documentsui" android:label="Performance tests for DocumentsUI" /> </manifest> packages/DocumentsUI/perf-tests/src/com/android/documentsui/FilesActivityPerfTest.java 0 → 100644 +144 −0 Original line number Diff line number Diff line /* * 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_1_ID; import android.app.Activity; import android.net.Uri; import android.os.Bundle; import android.os.RemoteException; import android.test.suitebuilder.annotation.LargeTest; import android.util.Log; import android.view.KeyEvent; import com.android.documentsui.model.RootInfo; import com.android.documentsui.EventListener; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; import java.util.concurrent.CountDownLatch; @LargeTest public class FilesActivityPerfTest extends ActivityTest<FilesActivity> { // Constants starting with KEY_ are used to report metrics to APCT. private static final String KEY_FILES_LISTED_PERFORMANCE_FIRST = "files-listed-performance-first"; private static final String KEY_FILES_LISTED_PERFORMANCE_MEDIAN = "files-listed-performance-median"; private static final String TESTED_URI = "content://com.android.documentsui.stressprovider/document/STRESS_ROOT_1_DOC"; private static final int NUM_MEASUREMENTS = 10; public FilesActivityPerfTest() { super(FilesActivity.class); } @Override protected RootInfo getInitialRoot() { return rootDir0; } @Override protected String getTestingProviderAuthority() { return DEFAULT_AUTHORITY; } @Override protected void setupTestingRoots() throws RemoteException { rootDir0 = mDocsHelper.getRoot(STRESS_ROOT_0_ID); rootDir1 = mDocsHelper.getRoot(STRESS_ROOT_1_ID); } @Override public void initTestFiles() throws RemoteException { // Nothing to create, already done by StressProvider. } public void testFilesListedPerformance() throws Exception { final BaseActivity activity = getActivity(); final List<Long> measurements = new ArrayList<Long>(); CountDownLatch signal; EventListener listener; for (int i = 0; i < 10; i++) { signal = new CountDownLatch(1); listener = new EventListener() { @Override public void onDirectoryNavigated(Uri uri) { if (uri != null && TESTED_URI.equals(uri.toString())) { mStartTime = System.currentTimeMillis(); } else { mStartTime = -1; } } @Override public void onDirectoryLoaded(Uri uri) { if (uri == null || !TESTED_URI.equals(uri.toString())) { return; } assertTrue(mStartTime != -1); getInstrumentation().waitForIdle(new Runnable() { @Override public void run() { assertTrue(mStartTime != -1); measurements.add(System.currentTimeMillis() - mStartTime); signal.countDown(); } }); } private long mStartTime = -1; }; try { activity.addEventListener(listener); bots.roots.openRoot(STRESS_ROOT_1_ID); signal.await(); } finally { activity.removeEventListener(listener); } assertEquals(i, measurements.size()); // Go back to the empty root. bots.roots.openRoot(STRESS_ROOT_0_ID); } assertEquals(NUM_MEASUREMENTS, measurements.size()); final Bundle status = new Bundle(); status.putDouble(KEY_FILES_LISTED_PERFORMANCE_FIRST, measurements.get(0)); final Long[] rawMeasurements = measurements.toArray(new Long[NUM_MEASUREMENTS]); Arrays.sort(rawMeasurements); final long median = rawMeasurements[NUM_MEASUREMENTS / 2 - 1]; status.putDouble(KEY_FILES_LISTED_PERFORMANCE_MEDIAN, median); getInstrumentation().sendStatus(Activity.RESULT_OK, status); } } packages/DocumentsUI/perf-tests/src/com/android/documentsui/StressProvider.java 0 → 100644 +149 −0 Original line number Diff line number Diff line /* * 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 android.content.Context; import android.content.pm.ProviderInfo; import android.database.Cursor; import android.database.MatrixCursor.RowBuilder; import android.database.MatrixCursor; import android.os.CancellationSignal; import android.os.FileUtils; import android.os.ParcelFileDescriptor; import android.provider.DocumentsContract.Document; import android.provider.DocumentsContract.Root; import android.provider.DocumentsContract; import android.provider.DocumentsProvider; import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.Random; /** * Provider with thousands of files for testing loading time of directories in DocumentsUI. * It doesn't support any file operations. */ public class StressProvider extends DocumentsProvider { public static final String DEFAULT_AUTHORITY = "com.android.documentsui.stressprovider"; // Empty root. public static final String STRESS_ROOT_0_ID = "STRESS_ROOT_0"; // Root with thousands of items. public static final String STRESS_ROOT_1_ID = "STRESS_ROOT_1"; 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[] DEFAULT_ROOT_PROJECTION = new String[] { Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_TITLE, Root.COLUMN_DOCUMENT_ID, Root.COLUMN_AVAILABLE_BYTES }; private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] { Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE, Document.COLUMN_DISPLAY_NAME, Document.COLUMN_LAST_MODIFIED, Document.COLUMN_FLAGS, Document.COLUMN_SIZE, }; private String mAuthority = DEFAULT_AUTHORITY; private ArrayList<String> mIds = new ArrayList<>(); @Override public void attachInfo(Context context, ProviderInfo info) { mAuthority = info.authority; super.attachInfo(context, info); } @Override public boolean onCreate() { mIds = new ArrayList(); for (int i = 0; i < 10000; i++) { mIds.add(createRandomId(i)); } mIds.add(STRESS_ROOT_0_DOC_ID); mIds.add(STRESS_ROOT_1_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); return result; } @Override public Cursor queryDocument(String documentId, String[] projection) throws FileNotFoundException { final MatrixCursor result = new MatrixCursor(DEFAULT_DOCUMENT_PROJECTION); includeDocument(result, documentId); return result; } @Override 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); } } return result; } @Override public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal) throws FileNotFoundException { throw new UnsupportedOperationException(); } private void includeRoot(MatrixCursor result, String rootId, String docId) { final RowBuilder row = result.newRow(); row.add(Root.COLUMN_ROOT_ID, rootId); row.add(Root.COLUMN_FLAGS, 0); row.add(Root.COLUMN_TITLE, rootId); row.add(Root.COLUMN_DOCUMENT_ID, docId); } private void includeDocument(MatrixCursor result, String id) { 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_FLAGS, 0); row.add(Document.COLUMN_LAST_MODIFIED, null); } private static String getDocumentIdForFile(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)); } builder.append(index); // Append a number to guarantee uniqueness. return builder.toString(); } } packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java +26 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import android.provider.DocumentsContract.Root; import android.support.annotation.CallSuper; import android.support.annotation.LayoutRes; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; Loading Loading @@ -67,6 +68,7 @@ public abstract class BaseActivity extends Activity SearchViewManager mSearchManager; DrawerController mDrawer; NavigationView mNavigator; List<EventListener> mEventListeners = new ArrayList<>(); private final String mTag; Loading Loading @@ -329,6 +331,8 @@ public abstract class BaseActivity extends Activity void openContainerDocument(DocumentInfo doc) { assert(doc.isContainer()); notifyDirectoryNavigated(doc.derivedUri); mState.pushDocument(doc); // Show an opening animation only if pressing "back" would get us back to the // previous directory. Especially after opening a root document, pressing Loading Loading @@ -594,6 +598,28 @@ public abstract class BaseActivity extends Activity return super.onKeyDown(keyCode, event); } @VisibleForTesting public void addEventListener(EventListener listener) { mEventListeners.add(listener); } @VisibleForTesting public void removeEventListener(EventListener listener) { mEventListeners.remove(listener); } public void notifyDirectoryLoaded(Uri uri) { for (EventListener listener : mEventListeners) { listener.onDirectoryLoaded(uri); } } void notifyDirectoryNavigated(Uri uri) { for (EventListener listener : mEventListeners) { listener.onDirectoryNavigated(uri); } } /** * Toggles focus between the navigation drawer and the directory listing. If the drawer isn't * locked, open/close it as appropriate. Loading Loading
packages/DocumentsUI/perf-tests/Android.mk 0 → 100644 +22 −0 Original line number Diff line number Diff line LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests #LOCAL_SDK_VERSION := current LOCAL_SRC_FILES := $(call all-java-files-under, src) \ $(call all-java-files-under, ../tests/src/com/android/documentsui/bots) \ ../tests/src/com/android/documentsui/ActivityTest.java \ ../tests/src/com/android/documentsui/DocumentsProviderHelper.java \ ../tests/src/com/android/documentsui/StubProvider.java LOCAL_JAVA_LIBRARIES := android.test.runner LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 mockito-target ub-uiautomator LOCAL_PACKAGE_NAME := DocumentsUIPerfTests LOCAL_INSTRUMENTATION_FOR := DocumentsUI LOCAL_CERTIFICATE := platform include $(BUILD_PACKAGE)
packages/DocumentsUI/perf-tests/AndroidManifest.xml 0 → 100644 +24 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.documentsui.perftests"> <application> <uses-library android:name="android.test.runner" /> <provider android:name="com.android.documentsui.StressProvider" android:authorities="com.android.documentsui.stressprovider" android:exported="true" android:grantUriPermissions="true" android:permission="android.permission.MANAGE_DOCUMENTS" android:enabled="true"> <intent-filter> <action android:name="android.content.action.DOCUMENTS_PROVIDER" /> </intent-filter> </provider> </application> <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.android.documentsui" android:label="Performance tests for DocumentsUI" /> </manifest>
packages/DocumentsUI/perf-tests/src/com/android/documentsui/FilesActivityPerfTest.java 0 → 100644 +144 −0 Original line number Diff line number Diff line /* * 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_1_ID; import android.app.Activity; import android.net.Uri; import android.os.Bundle; import android.os.RemoteException; import android.test.suitebuilder.annotation.LargeTest; import android.util.Log; import android.view.KeyEvent; import com.android.documentsui.model.RootInfo; import com.android.documentsui.EventListener; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; import java.util.concurrent.CountDownLatch; @LargeTest public class FilesActivityPerfTest extends ActivityTest<FilesActivity> { // Constants starting with KEY_ are used to report metrics to APCT. private static final String KEY_FILES_LISTED_PERFORMANCE_FIRST = "files-listed-performance-first"; private static final String KEY_FILES_LISTED_PERFORMANCE_MEDIAN = "files-listed-performance-median"; private static final String TESTED_URI = "content://com.android.documentsui.stressprovider/document/STRESS_ROOT_1_DOC"; private static final int NUM_MEASUREMENTS = 10; public FilesActivityPerfTest() { super(FilesActivity.class); } @Override protected RootInfo getInitialRoot() { return rootDir0; } @Override protected String getTestingProviderAuthority() { return DEFAULT_AUTHORITY; } @Override protected void setupTestingRoots() throws RemoteException { rootDir0 = mDocsHelper.getRoot(STRESS_ROOT_0_ID); rootDir1 = mDocsHelper.getRoot(STRESS_ROOT_1_ID); } @Override public void initTestFiles() throws RemoteException { // Nothing to create, already done by StressProvider. } public void testFilesListedPerformance() throws Exception { final BaseActivity activity = getActivity(); final List<Long> measurements = new ArrayList<Long>(); CountDownLatch signal; EventListener listener; for (int i = 0; i < 10; i++) { signal = new CountDownLatch(1); listener = new EventListener() { @Override public void onDirectoryNavigated(Uri uri) { if (uri != null && TESTED_URI.equals(uri.toString())) { mStartTime = System.currentTimeMillis(); } else { mStartTime = -1; } } @Override public void onDirectoryLoaded(Uri uri) { if (uri == null || !TESTED_URI.equals(uri.toString())) { return; } assertTrue(mStartTime != -1); getInstrumentation().waitForIdle(new Runnable() { @Override public void run() { assertTrue(mStartTime != -1); measurements.add(System.currentTimeMillis() - mStartTime); signal.countDown(); } }); } private long mStartTime = -1; }; try { activity.addEventListener(listener); bots.roots.openRoot(STRESS_ROOT_1_ID); signal.await(); } finally { activity.removeEventListener(listener); } assertEquals(i, measurements.size()); // Go back to the empty root. bots.roots.openRoot(STRESS_ROOT_0_ID); } assertEquals(NUM_MEASUREMENTS, measurements.size()); final Bundle status = new Bundle(); status.putDouble(KEY_FILES_LISTED_PERFORMANCE_FIRST, measurements.get(0)); final Long[] rawMeasurements = measurements.toArray(new Long[NUM_MEASUREMENTS]); Arrays.sort(rawMeasurements); final long median = rawMeasurements[NUM_MEASUREMENTS / 2 - 1]; status.putDouble(KEY_FILES_LISTED_PERFORMANCE_MEDIAN, median); getInstrumentation().sendStatus(Activity.RESULT_OK, status); } }
packages/DocumentsUI/perf-tests/src/com/android/documentsui/StressProvider.java 0 → 100644 +149 −0 Original line number Diff line number Diff line /* * 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 android.content.Context; import android.content.pm.ProviderInfo; import android.database.Cursor; import android.database.MatrixCursor.RowBuilder; import android.database.MatrixCursor; import android.os.CancellationSignal; import android.os.FileUtils; import android.os.ParcelFileDescriptor; import android.provider.DocumentsContract.Document; import android.provider.DocumentsContract.Root; import android.provider.DocumentsContract; import android.provider.DocumentsProvider; import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.Random; /** * Provider with thousands of files for testing loading time of directories in DocumentsUI. * It doesn't support any file operations. */ public class StressProvider extends DocumentsProvider { public static final String DEFAULT_AUTHORITY = "com.android.documentsui.stressprovider"; // Empty root. public static final String STRESS_ROOT_0_ID = "STRESS_ROOT_0"; // Root with thousands of items. public static final String STRESS_ROOT_1_ID = "STRESS_ROOT_1"; 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[] DEFAULT_ROOT_PROJECTION = new String[] { Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_TITLE, Root.COLUMN_DOCUMENT_ID, Root.COLUMN_AVAILABLE_BYTES }; private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] { Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE, Document.COLUMN_DISPLAY_NAME, Document.COLUMN_LAST_MODIFIED, Document.COLUMN_FLAGS, Document.COLUMN_SIZE, }; private String mAuthority = DEFAULT_AUTHORITY; private ArrayList<String> mIds = new ArrayList<>(); @Override public void attachInfo(Context context, ProviderInfo info) { mAuthority = info.authority; super.attachInfo(context, info); } @Override public boolean onCreate() { mIds = new ArrayList(); for (int i = 0; i < 10000; i++) { mIds.add(createRandomId(i)); } mIds.add(STRESS_ROOT_0_DOC_ID); mIds.add(STRESS_ROOT_1_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); return result; } @Override public Cursor queryDocument(String documentId, String[] projection) throws FileNotFoundException { final MatrixCursor result = new MatrixCursor(DEFAULT_DOCUMENT_PROJECTION); includeDocument(result, documentId); return result; } @Override 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); } } return result; } @Override public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal) throws FileNotFoundException { throw new UnsupportedOperationException(); } private void includeRoot(MatrixCursor result, String rootId, String docId) { final RowBuilder row = result.newRow(); row.add(Root.COLUMN_ROOT_ID, rootId); row.add(Root.COLUMN_FLAGS, 0); row.add(Root.COLUMN_TITLE, rootId); row.add(Root.COLUMN_DOCUMENT_ID, docId); } private void includeDocument(MatrixCursor result, String id) { 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_FLAGS, 0); row.add(Document.COLUMN_LAST_MODIFIED, null); } private static String getDocumentIdForFile(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)); } builder.append(index); // Append a number to guarantee uniqueness. return builder.toString(); } }
packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java +26 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import android.provider.DocumentsContract.Root; import android.support.annotation.CallSuper; import android.support.annotation.LayoutRes; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; Loading Loading @@ -67,6 +68,7 @@ public abstract class BaseActivity extends Activity SearchViewManager mSearchManager; DrawerController mDrawer; NavigationView mNavigator; List<EventListener> mEventListeners = new ArrayList<>(); private final String mTag; Loading Loading @@ -329,6 +331,8 @@ public abstract class BaseActivity extends Activity void openContainerDocument(DocumentInfo doc) { assert(doc.isContainer()); notifyDirectoryNavigated(doc.derivedUri); mState.pushDocument(doc); // Show an opening animation only if pressing "back" would get us back to the // previous directory. Especially after opening a root document, pressing Loading Loading @@ -594,6 +598,28 @@ public abstract class BaseActivity extends Activity return super.onKeyDown(keyCode, event); } @VisibleForTesting public void addEventListener(EventListener listener) { mEventListeners.add(listener); } @VisibleForTesting public void removeEventListener(EventListener listener) { mEventListeners.remove(listener); } public void notifyDirectoryLoaded(Uri uri) { for (EventListener listener : mEventListeners) { listener.onDirectoryLoaded(uri); } } void notifyDirectoryNavigated(Uri uri) { for (EventListener listener : mEventListeners) { listener.onDirectoryNavigated(uri); } } /** * Toggles focus between the navigation drawer and the directory listing. If the drawer isn't * locked, open/close it as appropriate. Loading