From a34bbd9167774e796c1e3b717e1d78ae7a5cc1bb Mon Sep 17 00:00:00 2001 From: Kelvin Kwan Date: Mon, 10 Feb 2020 23:49:21 +0000 Subject: startActivity with proper user and uri according to the attached userId Now we should able to preview document across user and return correct uri to ACTION_GET_CONTENT Bug: 148264890 Test: manual Test: atest DocumentsUIGoogleTests Change-Id: I231e996244cce455a3be7a9b7569bba286da005d --- .../android/documentsui/AbstractActionHandler.java | 8 +++---- src/com/android/documentsui/ActionHandler.java | 3 ++- src/com/android/documentsui/UserIdManager.java | 5 ++++- src/com/android/documentsui/base/DocumentInfo.java | 12 ++++++++++ src/com/android/documentsui/base/UserId.java | 16 +++++++++++++ .../android/documentsui/files/ActionHandler.java | 10 ++++----- .../documentsui/files/QuickViewIntentBuilder.java | 10 ++++----- .../documentsui/inspector/InspectorController.java | 2 +- .../inspector/actions/ShowInProviderAction.java | 3 +-- .../android/documentsui/picker/ActionHandler.java | 5 +++-- .../android/documentsui/picker/PickActivity.java | 4 ++-- src/com/android/documentsui/sidebar/AppItem.java | 2 +- .../documentsui/sidebar/RootAndAppItem.java | 2 +- .../com/android/documentsui/TestActivity.java | 26 +++++++++++++++++++--- .../com/android/documentsui/testing/TestEnv.java | 20 +++++++++++++---- .../documentsui/testing/TestProvidersAccess.java | 10 ++++++--- .../inspector/InspectorControllerTest.java | 14 ++++++++++-- .../documentsui/picker/ActionHandlerTest.java | 11 +++++++++ 18 files changed, 126 insertions(+), 37 deletions(-) diff --git a/src/com/android/documentsui/AbstractActionHandler.java b/src/com/android/documentsui/AbstractActionHandler.java index bee4aac5a..b18fabbaf 100644 --- a/src/com/android/documentsui/AbstractActionHandler.java +++ b/src/com/android/documentsui/AbstractActionHandler.java @@ -264,7 +264,7 @@ public abstract class AbstractActionHandler getUserIdsInternal() { + private List getUserIdsInternal() { final List result = new ArrayList<>(); result.add(mCurrentUser); diff --git a/src/com/android/documentsui/base/DocumentInfo.java b/src/com/android/documentsui/base/DocumentInfo.java index db11933d8..e1d9234f3 100644 --- a/src/com/android/documentsui/base/DocumentInfo.java +++ b/src/com/android/documentsui/base/DocumentInfo.java @@ -325,6 +325,18 @@ public class DocumentInfo implements Durable, Parcelable { return (flags & Document.FLAG_DIR_PREFERS_LAST_MODIFIED) != 0; } + /** + * Returns a document uri representing this {@link DocumentInfo}. The URI contains user + * information. Use this when uri is needed externally. For usage within DocsUI, use + * {@link #derivedUri}. + */ + public Uri getDocumentUri() { + if (UserId.CURRENT_USER.equals(userId)) { + return derivedUri; + } + return userId.buildDocumentUriAsUser(authority, documentId); + } + @Override public int hashCode() { return userId.hashCode() + derivedUri.hashCode() + mimeType.hashCode(); diff --git a/src/com/android/documentsui/base/UserId.java b/src/com/android/documentsui/base/UserId.java index 89a38d26c..1b6b3182f 100644 --- a/src/com/android/documentsui/base/UserId.java +++ b/src/com/android/documentsui/base/UserId.java @@ -20,11 +20,13 @@ import static androidx.core.util.Preconditions.checkNotNull; import android.content.ContentResolver; import android.content.Context; +import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; +import android.provider.DocumentsContract; import androidx.annotation.VisibleForTesting; import androidx.loader.content.CursorLoader; @@ -118,6 +120,20 @@ public final class UserId { return userManager.isManagedProfile(mUserHandle.getIdentifier()); } + /** + * Returns a document uri representing this user. + */ + public Uri buildDocumentUriAsUser(String authority, String documentId) { + return DocumentsContract.buildDocumentUriAsUser(authority, documentId, mUserHandle); + } + + /** + * Starts activity for this user + */ + public void startActivityAsUser(Context context, Intent intent) { + context.startActivityAsUser(intent, mUserHandle); + } + /** * Returns an identifier stored in this user id. This can be used to recreate the {@link UserId} * by {@link UserId#of(int)}. diff --git a/src/com/android/documentsui/files/ActionHandler.java b/src/com/android/documentsui/files/ActionHandler.java index 1a504ce8a..7b17246e2 100644 --- a/src/com/android/documentsui/files/ActionHandler.java +++ b/src/com/android/documentsui/files/ActionHandler.java @@ -154,7 +154,7 @@ public class ActionHandler 1) { intent = new Intent(Intent.ACTION_SEND_MULTIPLE); @@ -378,7 +378,7 @@ public class ActionHandler uris = new ArrayList<>(); for (DocumentInfo doc : docs) { mimeTypes.add(doc.mimeType); - uris.add(doc.derivedUri); + uris.add(doc.getDocumentUri()); } intent.setType(MimeTypes.findCommonMimeType(mimeTypes)); @@ -546,7 +546,7 @@ public class ActionHandler extends AbstractActionH } @Override - public void showAppDetails(ResolveInfo info) { + public void showAppDetails(ResolveInfo info, UserId userId) { mInjector.pickResult.increaseActionCount(); final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.fromParts("package", info.activityInfo.packageName, null)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); - mActivity.startActivity(intent); + userId.startActivityAsUser(mActivity, intent); } @Override diff --git a/src/com/android/documentsui/picker/PickActivity.java b/src/com/android/documentsui/picker/PickActivity.java index f7f2ebe80..3666716a9 100644 --- a/src/com/android/documentsui/picker/PickActivity.java +++ b/src/com/android/documentsui/picker/PickActivity.java @@ -361,7 +361,7 @@ public class PickActivity extends BaseActivity implements ActionHandler.Addons { mSearchManager.recordHistory(); } else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) { // Explicit file picked, return - mInjector.actions.finishPicking(doc.derivedUri); + mInjector.actions.finishPicking(doc.getDocumentUri()); mSearchManager.recordHistory(); } else if (mState.action == ACTION_CREATE) { // Replace selected file @@ -375,7 +375,7 @@ public class PickActivity extends BaseActivity implements ActionHandler.Addons { final int size = docs.size(); final Uri[] uris = new Uri[size]; for (int i = 0; i < size; i++) { - uris[i] = docs.get(i).derivedUri; + uris[i] = docs.get(i).getDocumentUri(); } mInjector.actions.finishPicking(uris); mSearchManager.recordHistory(); diff --git a/src/com/android/documentsui/sidebar/AppItem.java b/src/com/android/documentsui/sidebar/AppItem.java index 0487aa02e..06fffaab1 100644 --- a/src/com/android/documentsui/sidebar/AppItem.java +++ b/src/com/android/documentsui/sidebar/AppItem.java @@ -71,7 +71,7 @@ public class AppItem extends Item { @Override boolean showAppDetails() { - mActionHandler.showAppDetails(info); + mActionHandler.showAppDetails(info, userId); return true; } diff --git a/src/com/android/documentsui/sidebar/RootAndAppItem.java b/src/com/android/documentsui/sidebar/RootAndAppItem.java index c797febbb..6630d8bbd 100644 --- a/src/com/android/documentsui/sidebar/RootAndAppItem.java +++ b/src/com/android/documentsui/sidebar/RootAndAppItem.java @@ -41,7 +41,7 @@ class RootAndAppItem extends RootItem { @Override boolean showAppDetails() { - mActionHandler.showAppDetails(resolveInfo); + mActionHandler.showAppDetails(resolveInfo, userId); return true; } diff --git a/tests/common/com/android/documentsui/TestActivity.java b/tests/common/com/android/documentsui/TestActivity.java index 103fb404b..53f0792df 100644 --- a/tests/common/com/android/documentsui/TestActivity.java +++ b/tests/common/com/android/documentsui/TestActivity.java @@ -18,9 +18,6 @@ package com.android.documentsui; import static junit.framework.Assert.assertEquals; -import androidx.annotation.Nullable; -import androidx.fragment.app.FragmentActivity; - import android.app.ActivityManager; import android.app.LoaderManager; import android.content.ComponentName; @@ -31,9 +28,13 @@ import android.content.IntentSender; import android.content.pm.PackageManager; import android.content.res.Resources; import android.net.Uri; +import android.os.UserHandle; import android.test.mock.MockContentResolver; import android.util.Pair; +import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; + import com.android.documentsui.AbstractActionHandler.CommonAddons; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.RootInfo; @@ -57,12 +58,14 @@ public abstract class TestActivity extends AbstractBase { public TestPackageManager packageMgr; public Intent intent; public RootInfo currentRoot; + public UserHandle currentUserHandle; public MockContentResolver contentResolver; public TestLoaderManager loaderManager; public TestSupportLoaderManager supportLoaderManager; public ActivityManager activityManager; public TestEventListener startActivity; + public TestEventListener> startActivityAsUser; public TestEventListener startService; public TestEventListener> startIntentSender; public TestEventListener rootPicked; @@ -82,8 +85,10 @@ public abstract class TestActivity extends AbstractBase { resources = TestResources.create(); packageMgr = TestPackageManager.create(); intent = new Intent(); + currentUserHandle = env.userHandle; startActivity = new TestEventListener<>(); + startActivityAsUser = new TestEventListener<>(); startService = new TestEventListener<>(); startIntentSender = new TestEventListener<>(); rootPicked = new TestEventListener<>(); @@ -107,10 +112,25 @@ public abstract class TestActivity extends AbstractBase { startActivity.accept(intent); } + @Override + public final void startActivityAsUser(Intent intent, UserHandle userHandle) { + if (userHandle.equals(currentUserHandle)) { + startActivity(intent); + } else { + startActivityAsUser.accept(new Pair<>(intent, userHandle)); + } + } + public final void assertActivityStarted(String expectedAction) { assertEquals(expectedAction, startActivity.getLastValue().getAction()); } + public final void assertActivityAsUserStarted(String expectedAction, UserHandle userHandle) { + Pair intentUserHandle = startActivityAsUser.getLastValue(); + assertEquals(expectedAction, intentUserHandle.first.getAction()); + assertEquals(intentUserHandle.second, userHandle); + } + @Override public final ComponentName startService(Intent intent) { startService.accept(intent); diff --git a/tests/common/com/android/documentsui/testing/TestEnv.java b/tests/common/com/android/documentsui/testing/TestEnv.java index a75c0034c..b78d7316b 100644 --- a/tests/common/com/android/documentsui/testing/TestEnv.java +++ b/tests/common/com/android/documentsui/testing/TestEnv.java @@ -16,6 +16,7 @@ package com.android.documentsui.testing; import android.content.Context; +import android.os.UserHandle; import android.provider.DocumentsContract.Document; import android.test.mock.MockContentResolver; @@ -60,6 +61,10 @@ public class TestEnv { public static DocumentInfo FILE_VIRTUAL; public static DocumentInfo FILE_READ_ONLY; + public static class OtherUser { + public static DocumentInfo FILE_PNG; + } + public final TestScheduledExecutorService mExecutor; public final State state = new State(); public final TestProvidersAccess providers = new TestProvidersAccess(); @@ -72,16 +77,20 @@ public class TestEnv { public final TestSearchViewManager searchViewManager; public final Injector injector; public final Features features; + public final UserId userId; + public final UserHandle userHandle; public final MockContentResolver contentResolver; public final Map mockProviders; - private TestEnv(Context context, Features features, String authority) { + private TestEnv(Context context, Features features, String authority, UserId userId) { this.features = features; + this.userId = userId; + userHandle = UserHandle.of(userId.getIdentifier()); state.sortModel = SortModel.createModel(); mExecutor = new TestScheduledExecutorService(); - model = new TestModel(UserId.DEFAULT_USER, authority, features); - archiveModel = new TestModel(UserId.DEFAULT_USER, ArchivesProvider.AUTHORITY, features); + model = new TestModel(userId, authority, features); + archiveModel = new TestModel(userId, ArchivesProvider.AUTHORITY, features); selectionMgr = SelectionHelpers.createTestInstance(); searchViewManager = new TestSearchViewManager(); injector = new Injector( @@ -134,7 +143,7 @@ public class TestEnv { } private static TestEnv create(Context context, Features features, String authority) { - TestEnv env = new TestEnv(context, features, authority); + TestEnv env = new TestEnv(context, features, authority, TestProvidersAccess.USER_ID); env.reset(); return env; } @@ -170,6 +179,9 @@ public class TestEnv { | Document.FLAG_SUPPORTS_DELETE | Document.FLAG_SUPPORTS_RENAME); + OtherUser.FILE_PNG = model.createFile("work.png"); + OtherUser.FILE_PNG.userId = TestProvidersAccess.OtherUser.USER_ID; + archiveModel.update(); model.update(); } diff --git a/tests/common/com/android/documentsui/testing/TestProvidersAccess.java b/tests/common/com/android/documentsui/testing/TestProvidersAccess.java index 2ebbae0e5..6d7a1aca3 100644 --- a/tests/common/com/android/documentsui/testing/TestProvidersAccess.java +++ b/tests/common/com/android/documentsui/testing/TestProvidersAccess.java @@ -15,6 +15,7 @@ */ package com.android.documentsui.testing; +import android.os.UserHandle; import android.provider.DocumentsContract.Root; import com.android.documentsui.InspectorProvider; @@ -34,6 +35,8 @@ import javax.annotation.Nullable; public class TestProvidersAccess implements ProvidersAccess { + public static final UserId USER_ID = UserId.DEFAULT_USER; + public static final RootInfo DOWNLOADS; public static final RootInfo HOME; public static final RootInfo HAMMY; @@ -48,8 +51,7 @@ public class TestProvidersAccess implements ProvidersAccess { public static final RootInfo NO_TREE_ROOT; static { - UserId userId = UserId.DEFAULT_USER; - + UserId userId = USER_ID; DOWNLOADS = new RootInfo() {{ flags = Root.FLAG_SUPPORTS_CREATE; }}; @@ -154,7 +156,9 @@ public class TestProvidersAccess implements ProvidersAccess { } public static class OtherUser { - public static final UserId USER_ID = UserId.of(UserId.DEFAULT_USER.getIdentifier() + 1); + public static final UserHandle USER_HANDLE = UserHandle.of( + TestProvidersAccess.USER_ID.getIdentifier() + 1); + public static final UserId USER_ID = UserId.of(OtherUser.USER_HANDLE); public static final RootInfo DOWNLOADS; diff --git a/tests/unit/com/android/documentsui/inspector/InspectorControllerTest.java b/tests/unit/com/android/documentsui/inspector/InspectorControllerTest.java index d35a6dedd..52d3c9061 100644 --- a/tests/unit/com/android/documentsui/inspector/InspectorControllerTest.java +++ b/tests/unit/com/android/documentsui/inspector/InspectorControllerTest.java @@ -26,6 +26,7 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.os.Looper; +import android.os.UserHandle; import android.provider.DocumentsContract; import android.provider.DocumentsContract.Document; import android.test.suitebuilder.annotation.SmallTest; @@ -84,8 +85,8 @@ public class InspectorControllerTest { @Before public void setUp() throws Exception { - mUserId = UserId.DEFAULT_USER; mEnv = TestEnv.create(); + mUserId = mEnv.userId; mPm = TestPackageManager.create(); mLoaderManager = new TestLoaderManager(); mDataSupplier = new TestDataSupplier(); @@ -285,7 +286,7 @@ public class InspectorControllerTest { assertTrue(strUri.contains(TestEnv.FILE_JPG.displayName)); } - private static class TestActivity extends Activity { + private class TestActivity extends Activity { private @Nullable Intent started; @@ -293,6 +294,15 @@ public class InspectorControllerTest { public void startActivity(Intent intent) { started = intent; } + + @Override + public void startActivityAsUser(Intent intent, UserHandle user) { + if (user.equals(mEnv.userHandle)) { + startActivity(intent); + return; + } + throw new UnsupportedOperationException("not implemented"); + } } private static class TestAction implements ActionDisplay { diff --git a/tests/unit/com/android/documentsui/picker/ActionHandlerTest.java b/tests/unit/com/android/documentsui/picker/ActionHandlerTest.java index abcc6333b..57d4df7f5 100644 --- a/tests/unit/com/android/documentsui/picker/ActionHandlerTest.java +++ b/tests/unit/com/android/documentsui/picker/ActionHandlerTest.java @@ -579,6 +579,17 @@ public class ActionHandlerTest { mActivity.assertActivityStarted(Intent.ACTION_QUICK_VIEW); } + @Test + public void testPreviewItem_onOtherUser() throws Exception { + mActivity.resources.setQuickViewerPackage("corptropolis.viewer"); + mActivity.currentRoot = TestProvidersAccess.OtherUser.DOWNLOADS; + + mHandler.onDocumentOpened(TestEnv.OtherUser.FILE_PNG, ActionHandler.VIEW_TYPE_PREVIEW, + ActionHandler.VIEW_TYPE_REGULAR, true); + mActivity.assertActivityAsUserStarted(Intent.ACTION_QUICK_VIEW, + TestProvidersAccess.OtherUser.USER_HANDLE); + } + @Test public void testPreviewItem_archives() throws Exception { mActivity.resources.setQuickViewerPackage("corptropolis.viewer"); -- cgit v1.2.3-59-g8ed1b