am 998cfa2c: Merge "API to discover granted Uri permissions." into klp-dev
* commit '998cfa2c63c54a73d0c51d062408d370ed0b3107': API to discover granted Uri permissions.
This commit is contained in:
@@ -5587,8 +5587,10 @@ package android.content {
|
||||
method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]);
|
||||
method public static deprecated android.content.SyncInfo getCurrentSync();
|
||||
method public static java.util.List<android.content.SyncInfo> getCurrentSyncs();
|
||||
method public android.net.Uri[] getIncomingUriPermissionGrants(int, int);
|
||||
method public static int getIsSyncable(android.accounts.Account, java.lang.String);
|
||||
method public static boolean getMasterSyncAutomatically();
|
||||
method public android.net.Uri[] getOutgoingUriPermissionGrants(int, int);
|
||||
method public static java.util.List<android.content.PeriodicSync> getPeriodicSyncs(android.accounts.Account, java.lang.String);
|
||||
method public java.lang.String[] getStreamTypes(android.net.Uri, java.lang.String);
|
||||
method public static android.content.SyncAdapterType[] getSyncAdapterTypes();
|
||||
@@ -20353,6 +20355,7 @@ package android.provider {
|
||||
method public static android.net.Uri buildSearchUri(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
|
||||
method public static android.net.Uri buildSearchUri(android.net.Uri, java.lang.String);
|
||||
method public static java.lang.String getDocId(android.net.Uri);
|
||||
method public static android.net.Uri[] getOpenDocuments(android.content.Context);
|
||||
method public static java.lang.String getRootId(android.net.Uri);
|
||||
method public static java.lang.String getSearchQuery(android.net.Uri);
|
||||
method public static android.graphics.Bitmap getThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point);
|
||||
@@ -23369,11 +23372,14 @@ package android.test.mock {
|
||||
method public java.io.File getDatabasePath(java.lang.String);
|
||||
method public java.io.File getDir(java.lang.String, int);
|
||||
method public java.io.File getExternalCacheDir();
|
||||
method public java.io.File[] getExternalCacheDirs();
|
||||
method public java.io.File getExternalFilesDir(java.lang.String);
|
||||
method public java.io.File[] getExternalFilesDirs(java.lang.String);
|
||||
method public java.io.File getFileStreamPath(java.lang.String);
|
||||
method public java.io.File getFilesDir();
|
||||
method public android.os.Looper getMainLooper();
|
||||
method public java.io.File getObbDir();
|
||||
method public java.io.File[] getObbDirs();
|
||||
method public java.lang.String getPackageCodePath();
|
||||
method public android.content.pm.PackageManager getPackageManager();
|
||||
method public java.lang.String getPackageName();
|
||||
|
||||
@@ -1980,6 +1980,19 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
|
||||
reply.writeNoException();
|
||||
return true;
|
||||
}
|
||||
|
||||
case GET_GRANTED_URI_PERMISSIONS_TRANSACTION: {
|
||||
data.enforceInterface(IActivityManager.descriptor);
|
||||
final String sourcePackage = data.readString();
|
||||
final String targetPackage = data.readString();
|
||||
final int modeFlags = data.readInt();
|
||||
final int modeMask = data.readInt();
|
||||
final Uri[] uris = getGrantedUriPermissions(
|
||||
sourcePackage, targetPackage, modeFlags, modeMask);
|
||||
reply.writeNoException();
|
||||
reply.writeParcelableArray(uris, 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return super.onTransact(code, data, reply, flags);
|
||||
@@ -4540,5 +4553,23 @@ class ActivityManagerProxy implements IActivityManager
|
||||
reply.recycle();
|
||||
}
|
||||
|
||||
public Uri[] getGrantedUriPermissions(
|
||||
String sourcePackage, String targetPackage, int modeFlags, int modeMask)
|
||||
throws RemoteException {
|
||||
Parcel data = Parcel.obtain();
|
||||
Parcel reply = Parcel.obtain();
|
||||
data.writeInterfaceToken(IActivityManager.descriptor);
|
||||
data.writeString(sourcePackage);
|
||||
data.writeString(targetPackage);
|
||||
data.writeInt(modeFlags);
|
||||
data.writeInt(modeMask);
|
||||
mRemote.transact(GET_GRANTED_URI_PERMISSIONS_TRANSACTION, data, reply, 0);
|
||||
reply.readException();
|
||||
final Uri[] uris = (Uri[]) reply.readParcelableArray(null);
|
||||
data.recycle();
|
||||
reply.recycle();
|
||||
return uris;
|
||||
}
|
||||
|
||||
private IBinder mRemote;
|
||||
}
|
||||
|
||||
@@ -399,6 +399,10 @@ public interface IActivityManager extends IInterface {
|
||||
|
||||
public void restart() throws RemoteException;
|
||||
|
||||
public Uri[] getGrantedUriPermissions(
|
||||
String sourcePackage, String targetPackage, int modeFlags, int modeMask)
|
||||
throws RemoteException;
|
||||
|
||||
/*
|
||||
* Private non-Binder interfaces
|
||||
*/
|
||||
@@ -680,4 +684,5 @@ public interface IActivityManager extends IInterface {
|
||||
int NOTIFY_ACTIVITY_DRAWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+175;
|
||||
int REPORT_ACTIVITY_FULLY_DRAWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+176;
|
||||
int RESTART_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+177;
|
||||
int GET_GRANTED_URI_PERMISSIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+178;
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package android.content;
|
||||
|
||||
import dalvik.system.CloseGuard;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.app.ActivityThread;
|
||||
@@ -44,7 +42,8 @@ import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.EventLog;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import dalvik.system.CloseGuard;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@@ -1388,6 +1387,58 @@ public abstract class ContentResolver {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of all Uri permissions that have been granted <em>to</em> the
|
||||
* calling package, and which exactly match the requested flags. For
|
||||
* example, to return all Uris that the calling application has
|
||||
* <em>non-persistent</em> read access to:
|
||||
*
|
||||
* <pre class="prettyprint">
|
||||
* getIncomingUriPermissionGrants(Intent.FLAG_GRANT_READ_URI_PERMISSION,
|
||||
* Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_PERSIST_GRANT_URI_PERMISSION);
|
||||
* </pre>
|
||||
*
|
||||
* @param modeFlags any combination of
|
||||
* {@link Intent#FLAG_GRANT_READ_URI_PERMISSION},
|
||||
* {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}, or
|
||||
* {@link Intent#FLAG_PERSIST_GRANT_URI_PERMISSION}.
|
||||
* @param modeMask mask indicating which flags must match.
|
||||
*/
|
||||
public Uri[] getIncomingUriPermissionGrants(int modeFlags, int modeMask) {
|
||||
try {
|
||||
return ActivityManagerNative.getDefault()
|
||||
.getGrantedUriPermissions(null, getPackageName(), modeFlags, modeMask);
|
||||
} catch (RemoteException e) {
|
||||
return new Uri[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of all Uri permissions that have been granted <em>from</em> the
|
||||
* calling package, and which exactly match the requested flags. For
|
||||
* example, to return all Uris that the calling application has granted
|
||||
* <em>non-persistent</em> read access to:
|
||||
*
|
||||
* <pre class="prettyprint">
|
||||
* getOutgoingUriPermissionGrants(Intent.FLAG_GRANT_READ_URI_PERMISSION,
|
||||
* Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_PERSIST_GRANT_URI_PERMISSION);
|
||||
* </pre>
|
||||
*
|
||||
* @param modeFlags any combination of
|
||||
* {@link Intent#FLAG_GRANT_READ_URI_PERMISSION},
|
||||
* {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}, or
|
||||
* {@link Intent#FLAG_PERSIST_GRANT_URI_PERMISSION}.
|
||||
* @param modeMask mask indicating which flags must match.
|
||||
*/
|
||||
public Uri[] getOutgoingUriPermissionGrants(int modeFlags, int modeMask) {
|
||||
try {
|
||||
return ActivityManagerNative.getDefault()
|
||||
.getGrantedUriPermissions(getPackageName(), null, modeFlags, modeMask);
|
||||
} catch (RemoteException e) {
|
||||
return new Uri[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start an asynchronous sync operation. If you want to monitor the progress
|
||||
* of the sync you may register a SyncObserver. Only values of the following
|
||||
|
||||
@@ -19,7 +19,9 @@ package android.provider;
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.database.Cursor;
|
||||
@@ -30,6 +32,8 @@ import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.collect.Lists;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -201,19 +205,25 @@ public final class DocumentsContract {
|
||||
|
||||
public static String getRootId(Uri documentUri) {
|
||||
final List<String> paths = documentUri.getPathSegments();
|
||||
if (paths.size() < 2) {
|
||||
throw new IllegalArgumentException("Not a root: " + documentUri);
|
||||
}
|
||||
if (!PATH_ROOTS.equals(paths.get(0))) {
|
||||
throw new IllegalArgumentException();
|
||||
throw new IllegalArgumentException("Not a root: " + documentUri);
|
||||
}
|
||||
return paths.get(1);
|
||||
}
|
||||
|
||||
public static String getDocId(Uri documentUri) {
|
||||
final List<String> paths = documentUri.getPathSegments();
|
||||
if (paths.size() < 4) {
|
||||
throw new IllegalArgumentException("Not a document: " + documentUri);
|
||||
}
|
||||
if (!PATH_ROOTS.equals(paths.get(0))) {
|
||||
throw new IllegalArgumentException();
|
||||
throw new IllegalArgumentException("Not a document: " + documentUri);
|
||||
}
|
||||
if (!PATH_DOCS.equals(paths.get(2))) {
|
||||
throw new IllegalArgumentException();
|
||||
throw new IllegalArgumentException("Not a document: " + documentUri);
|
||||
}
|
||||
return paths.get(3);
|
||||
}
|
||||
@@ -358,6 +368,36 @@ public final class DocumentsContract {
|
||||
public static final String AVAILABLE_BYTES = "available_bytes";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of all documents that the calling package has "open." These
|
||||
* are Uris matching {@link DocumentsContract} to which persistent
|
||||
* read/write access has been granted, usually through
|
||||
* {@link Intent#ACTION_OPEN_DOCUMENT} or
|
||||
* {@link Intent#ACTION_CREATE_DOCUMENT}.
|
||||
*
|
||||
* @see Context#grantUriPermission(String, Uri, int)
|
||||
* @see ContentResolver#getIncomingUriPermissionGrants(int, int)
|
||||
*/
|
||||
public static Uri[] getOpenDocuments(Context context) {
|
||||
final int openedFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_PERSIST_GRANT_URI_PERMISSION;
|
||||
final Uri[] uris = context.getContentResolver()
|
||||
.getIncomingUriPermissionGrants(openedFlags, openedFlags);
|
||||
|
||||
// Filter to only include document providers
|
||||
final PackageManager pm = context.getPackageManager();
|
||||
final List<Uri> result = Lists.newArrayList();
|
||||
for (Uri uri : uris) {
|
||||
final ProviderInfo info = pm.resolveContentProvider(
|
||||
uri.getAuthority(), PackageManager.GET_META_DATA);
|
||||
if (info.metaData.containsKey(META_DATA_DOCUMENT_PROVIDER)) {
|
||||
result.add(uri);
|
||||
}
|
||||
}
|
||||
|
||||
return result.toArray(new Uri[result.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return thumbnail representing the document at the given URI. Callers are
|
||||
* responsible for their own caching. Given document must have
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.android.internal.os.BackgroundThread;
|
||||
import com.android.internal.os.BatteryStatsImpl;
|
||||
import com.android.internal.os.ProcessCpuTracker;
|
||||
import com.android.internal.os.TransferPipe;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.FastPrintWriter;
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.internal.util.MemInfoReader;
|
||||
@@ -705,8 +706,8 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
* to {@link UriPermission#uri} to {@link UriPermission}.
|
||||
*/
|
||||
@GuardedBy("this")
|
||||
private final SparseArray<HashMap<Uri, UriPermission>>
|
||||
mGrantedUriPermissions = new SparseArray<HashMap<Uri, UriPermission>>();
|
||||
private final SparseArray<ArrayMap<Uri, UriPermission>>
|
||||
mGrantedUriPermissions = new SparseArray<ArrayMap<Uri, UriPermission>>();
|
||||
|
||||
CoreSettingsObserver mCoreSettingsObserver;
|
||||
|
||||
@@ -5446,9 +5447,9 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
|
||||
private UriPermission findOrCreateUriPermissionLocked(
|
||||
String sourcePkg, String targetPkg, int targetUid, Uri uri) {
|
||||
HashMap<Uri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
|
||||
ArrayMap<Uri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
|
||||
if (targetUris == null) {
|
||||
targetUris = Maps.newHashMap();
|
||||
targetUris = Maps.newArrayMap();
|
||||
mGrantedUriPermissions.put(targetUid, targetUris);
|
||||
}
|
||||
|
||||
@@ -5467,7 +5468,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
if (uid == 0) {
|
||||
return true;
|
||||
}
|
||||
HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
|
||||
ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
|
||||
if (perms == null) return false;
|
||||
UriPermission perm = perms.get(uri);
|
||||
if (perm == null) return false;
|
||||
@@ -5794,7 +5795,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
void removeUriPermissionIfNeededLocked(UriPermission perm) {
|
||||
if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
|Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
|
||||
HashMap<Uri, UriPermission> perms
|
||||
ArrayMap<Uri, UriPermission> perms
|
||||
= mGrantedUriPermissions.get(perm.targetUid);
|
||||
if (perms != null) {
|
||||
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
|
||||
@@ -5837,7 +5838,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
final int NS = SEGMENTS.size();
|
||||
int N = mGrantedUriPermissions.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
HashMap<Uri, UriPermission> perms
|
||||
ArrayMap<Uri, UriPermission> perms
|
||||
= mGrantedUriPermissions.valueAt(i);
|
||||
Iterator<UriPermission> it = perms.values().iterator();
|
||||
toploop:
|
||||
@@ -6114,6 +6115,51 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri[] getGrantedUriPermissions(
|
||||
String sourcePackage, String targetPackage, int modeFlags, int modeMask) {
|
||||
enforceNotIsolatedCaller("getGrantedUriPermissions");
|
||||
synchronized (this) {
|
||||
// Verify that caller owns at least one of the requested packages
|
||||
final int uid = Binder.getCallingUid();
|
||||
final IPackageManager pm = AppGlobals.getPackageManager();
|
||||
final String[] callerPackages;
|
||||
try {
|
||||
callerPackages = pm.getPackagesForUid(uid);
|
||||
} catch (RemoteException e) {
|
||||
throw new SecurityException("Failed to find packages for UID " + uid);
|
||||
}
|
||||
final boolean callerOwnsSource = sourcePackage != null
|
||||
&& ArrayUtils.contains(callerPackages, sourcePackage);
|
||||
final boolean callerOwnsTarget = targetPackage != null
|
||||
&& ArrayUtils.contains(callerPackages, targetPackage);
|
||||
if (!(callerOwnsSource || callerOwnsTarget)) {
|
||||
throw new SecurityException("Caller " + Arrays.toString(callerPackages)
|
||||
+ " doesn't own " + sourcePackage + " or " + targetPackage);
|
||||
}
|
||||
|
||||
final ArrayList<Uri> result = Lists.newArrayList();
|
||||
final int size = mGrantedUriPermissions.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final ArrayMap<Uri, UriPermission> map = mGrantedUriPermissions.valueAt(i);
|
||||
final int mapSize = map.size();
|
||||
for (int j = 0; j < mapSize; j++) {
|
||||
final UriPermission perm = map.valueAt(j);
|
||||
final boolean sourceMatch = sourcePackage == null
|
||||
|| sourcePackage.equals(perm.sourcePkg);
|
||||
final boolean targetMatch = targetPackage == null
|
||||
|| targetPackage.equals(perm.targetPkg);
|
||||
final boolean modeMatch = (perm.modeFlags & modeMask) == modeFlags;
|
||||
if (sourceMatch && targetMatch && modeMatch) {
|
||||
result.add(perm.uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.toArray(new Uri[result.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
|
||||
synchronized (this) {
|
||||
@@ -6830,7 +6876,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
}
|
||||
}
|
||||
|
||||
HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
|
||||
ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
|
||||
if (perms != null) {
|
||||
for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
|
||||
if (uri.getKey().getAuthority().equals(cpi.authority)) {
|
||||
@@ -10731,7 +10777,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
if (dumpUid >= -1 && UserHandle.getAppId(uid) != dumpUid) {
|
||||
continue;
|
||||
}
|
||||
HashMap<Uri, UriPermission> perms
|
||||
ArrayMap<Uri, UriPermission> perms
|
||||
= mGrantedUriPermissions.valueAt(i);
|
||||
if (!printed) {
|
||||
if (needSep) pw.println();
|
||||
|
||||
Reference in New Issue
Block a user