From 77797400ec103b1691e1c3fa602c329b49ac18ca Mon Sep 17 00:00:00 2001 From: Ben Kwa Date: Fri, 29 May 2015 15:40:31 -0700 Subject: Enable apps to exclude their own roots from the DocumentsUI roots list. - Add DocumentsContract.EXTRA_EXCLUDE_SELF (boolean extra) - Add code to DocumentsActivity to cache the providers of the calling app if EXTRA_EXCLUDE_SELF is set on incoming Intents. - Add code to RootsCache to exclude roots from the calling app. - Add code to allow only system apps to use EXTRA_PACKAGE_NAME. Change-Id: Ia7cc2a1a297676c7b26f6e583042a4607d8c9a4e --- .../src/com/android/documentsui/BaseActivity.java | 43 +++++++++++++++++++++- .../com/android/documentsui/DocumentsActivity.java | 2 + .../src/com/android/documentsui/RootsCache.java | 6 +++ .../com/android/documentsui/model/RootInfo.java | 2 - .../com/android/documentsui/RootsCacheTest.java | 25 +++++++++++++ 5 files changed, 74 insertions(+), 4 deletions(-) (limited to 'packages/DocumentsUI') diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java index cb21131..8ea5816 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java @@ -25,6 +25,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.concurrent.Executor; @@ -32,6 +33,10 @@ import libcore.io.IoUtils; import android.app.Activity; import android.app.Fragment; import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.ProviderInfo; import android.database.Cursor; import android.net.Uri; import android.os.AsyncTask; @@ -232,9 +237,38 @@ abstract class BaseActivity extends Activity { invalidateOptionsMenu(); } + final List getExcludedAuthorities() { + List authorities = new ArrayList<>(); + if (getIntent().getBooleanExtra(DocumentsContract.EXTRA_EXCLUDE_SELF, false)) { + // Exclude roots provided by the calling package. + String packageName = getCallingPackageMaybeExtra(); + try { + PackageInfo pkgInfo = getPackageManager().getPackageInfo(packageName, + PackageManager.GET_PROVIDERS); + for (ProviderInfo provider: pkgInfo.providers) { + authorities.add(provider.authority); + } + } catch (PackageManager.NameNotFoundException e) { + Log.e(mTag, "Calling package name does not resolve: " + packageName); + } + } + return authorities; + } + final String getCallingPackageMaybeExtra() { - final String extra = getIntent().getStringExtra(DocumentsContract.EXTRA_PACKAGE_NAME); - return (extra != null) ? extra : getCallingPackage(); + String callingPackage = getCallingPackage(); + // System apps can set the calling package name using an extra. + try { + ApplicationInfo info = getPackageManager().getApplicationInfo(callingPackage, 0); + if (info.isSystemApp() || info.isUpdatedSystemApp()) { + final String extra = getIntent().getStringExtra(DocumentsContract.EXTRA_PACKAGE_NAME); + if (extra != null) { + callingPackage = extra; + } + } + } finally { + return callingPackage; + } } public static BaseActivity get(Fragment fragment) { @@ -287,6 +321,9 @@ abstract class BaseActivity extends Activity { /** Currently copying file */ public List selectedDocumentsForCopy = new ArrayList(); + /** Name of the package that started DocsUI */ + public List excludedAuthorities = new ArrayList<>(); + public static final int ACTION_OPEN = 1; public static final int ACTION_CREATE = 2; public static final int ACTION_GET_CONTENT = 3; @@ -327,6 +364,7 @@ abstract class BaseActivity extends Activity { out.writeString(currentSearch); out.writeMap(dirState); out.writeList(selectedDocumentsForCopy); + out.writeList(excludedAuthorities); } public static final Creator CREATOR = new Creator() { @@ -348,6 +386,7 @@ abstract class BaseActivity extends Activity { state.currentSearch = in.readString(); in.readMap(state.dirState, null); in.readList(state.selectedDocumentsForCopy, null); + in.readList(state.excludedAuthorities, null); return state; } diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java index da59d0e..69ae34e 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java @@ -256,6 +256,8 @@ public class DocumentsActivity extends BaseActivity { BaseActivity.DocumentsIntent.EXTRA_DIRECTORY_COPY, false); } + state.excludedAuthorities = getExcludedAuthorities(); + return state; } diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java index 27e8f20..fbcb938 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java @@ -383,6 +383,12 @@ public class RootsCache { continue; } + // Exclude roots from the calling package. + if (state.excludedAuthorities.contains(root.authority)) { + if (LOGD) Log.d(TAG, "Excluding root " + root.authority + " from calling package."); + continue; + } + matching.add(root); } return matching; diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java index 97d8ed0..ecf4d6c 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java +++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java @@ -55,7 +55,6 @@ public class RootInfo implements Durable, Parcelable { public String mimeTypes; /** Derived fields that aren't persisted */ - public String derivedPackageName; public String[] derivedMimeTypes; public int derivedIcon; @@ -75,7 +74,6 @@ public class RootInfo implements Durable, Parcelable { availableBytes = -1; mimeTypes = null; - derivedPackageName = null; derivedMimeTypes = null; derivedIcon = 0; } diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java index 7faa3ce..8c5bac1 100644 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java @@ -114,6 +114,31 @@ public class RootsCacheTest extends AndroidTestCase { RootsCache.getMatchingRoots(mRoots, mState)); } + public void testExcludedAuthorities() throws Exception { + final List roots = Lists.newArrayList(); + + // Set up some roots + for (int i = 0; i < 5; ++i) { + RootInfo root = new RootInfo(); + root.authority = "authority" + i; + roots.add(root); + } + // Make some allowed authorities + List allowedRoots = Lists.newArrayList( + roots.get(0), roots.get(2), roots.get(4)); + // Set up the excluded authority list + for (RootInfo root: roots) { + if (!allowedRoots.contains(root)) { + mState.excludedAuthorities.add(root.authority); + } + } + mState.acceptMimes = new String[] { "*/*" }; + + assertContainsExactly( + allowedRoots, + RootsCache.getMatchingRoots(roots, mState)); + } + private static void assertContainsExactly(List expected, List actual) { assertEquals(expected.size(), actual.size()); for (Object o : expected) { -- cgit v1.1