am d8691d73: Merge "Allow all apps to call ContentResolver.getType()." into gingerbread
Merge commit 'd8691d73d158acd9ffc63748126e822afd656707' into gingerbread-plus-aosp * commit 'd8691d73d158acd9ffc63748126e822afd656707': Allow all apps to call ContentResolver.getType().
This commit is contained in:
@@ -1272,6 +1272,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case GET_PROVIDER_MIME_TYPE_TRANSACTION: {
|
||||||
|
data.enforceInterface(IActivityManager.descriptor);
|
||||||
|
Uri uri = Uri.CREATOR.createFromParcel(data);
|
||||||
|
String type = getProviderMimeType(uri);
|
||||||
|
reply.writeNoException();
|
||||||
|
reply.writeString(type);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
case NEW_URI_PERMISSION_OWNER_TRANSACTION: {
|
case NEW_URI_PERMISSION_OWNER_TRANSACTION: {
|
||||||
data.enforceInterface(IActivityManager.descriptor);
|
data.enforceInterface(IActivityManager.descriptor);
|
||||||
String name = data.readString();
|
String name = data.readString();
|
||||||
@@ -2847,6 +2856,20 @@ class ActivityManagerProxy implements IActivityManager
|
|||||||
reply.recycle();
|
reply.recycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getProviderMimeType(Uri uri)
|
||||||
|
throws RemoteException {
|
||||||
|
Parcel data = Parcel.obtain();
|
||||||
|
Parcel reply = Parcel.obtain();
|
||||||
|
data.writeInterfaceToken(IActivityManager.descriptor);
|
||||||
|
uri.writeToParcel(data, 0);
|
||||||
|
mRemote.transact(GET_PROVIDER_MIME_TYPE_TRANSACTION, data, reply, 0);
|
||||||
|
reply.readException();
|
||||||
|
String res = reply.readString();
|
||||||
|
data.recycle();
|
||||||
|
reply.recycle();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
public IBinder newUriPermissionOwner(String name)
|
public IBinder newUriPermissionOwner(String name)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
Parcel data = Parcel.obtain();
|
Parcel data = Parcel.obtain();
|
||||||
|
|||||||
@@ -3287,12 +3287,20 @@ public final class ActivityThread {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final IContentProvider getProvider(Context context, String name) {
|
private final IContentProvider getExistingProvider(Context context, String name) {
|
||||||
synchronized(mProviderMap) {
|
synchronized(mProviderMap) {
|
||||||
final ProviderClientRecord pr = mProviderMap.get(name);
|
final ProviderClientRecord pr = mProviderMap.get(name);
|
||||||
if (pr != null) {
|
if (pr != null) {
|
||||||
return pr.mProvider;
|
return pr.mProvider;
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final IContentProvider getProvider(Context context, String name) {
|
||||||
|
IContentProvider existing = getExistingProvider(context, name);
|
||||||
|
if (existing != null) {
|
||||||
|
return existing;
|
||||||
}
|
}
|
||||||
|
|
||||||
IActivityManager.ContentProviderHolder holder = null;
|
IActivityManager.ContentProviderHolder holder = null;
|
||||||
@@ -3337,6 +3345,22 @@ public final class ActivityThread {
|
|||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final IContentProvider acquireExistingProvider(Context c, String name) {
|
||||||
|
IContentProvider provider = getExistingProvider(c, name);
|
||||||
|
if(provider == null)
|
||||||
|
return null;
|
||||||
|
IBinder jBinder = provider.asBinder();
|
||||||
|
synchronized(mProviderMap) {
|
||||||
|
ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
|
||||||
|
if(prc == null) {
|
||||||
|
mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
|
||||||
|
} else {
|
||||||
|
prc.count++;
|
||||||
|
} //end else
|
||||||
|
} //end synchronized
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
public final boolean releaseProvider(IContentProvider provider) {
|
public final boolean releaseProvider(IContentProvider provider) {
|
||||||
if(provider == null) {
|
if(provider == null) {
|
||||||
return false;
|
return false;
|
||||||
@@ -3345,7 +3369,7 @@ public final class ActivityThread {
|
|||||||
synchronized(mProviderMap) {
|
synchronized(mProviderMap) {
|
||||||
ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
|
ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
|
||||||
if(prc == null) {
|
if(prc == null) {
|
||||||
if(localLOGV) Slog.v(TAG, "releaseProvider::Weird shouldnt be here");
|
if(localLOGV) Slog.v(TAG, "releaseProvider::Weird shouldn't be here");
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
prc.count--;
|
prc.count--;
|
||||||
|
|||||||
@@ -1623,22 +1623,23 @@ class ContextImpl extends Context {
|
|||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
private static final class ApplicationContentResolver extends ContentResolver {
|
private static final class ApplicationContentResolver extends ContentResolver {
|
||||||
public ApplicationContentResolver(Context context,
|
public ApplicationContentResolver(Context context, ActivityThread mainThread) {
|
||||||
ActivityThread mainThread)
|
|
||||||
{
|
|
||||||
super(context);
|
super(context);
|
||||||
mMainThread = mainThread;
|
mMainThread = mainThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IContentProvider acquireProvider(Context context, String name)
|
protected IContentProvider acquireProvider(Context context, String name) {
|
||||||
{
|
|
||||||
return mMainThread.acquireProvider(context, name);
|
return mMainThread.acquireProvider(context, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean releaseProvider(IContentProvider provider)
|
protected IContentProvider acquireExistingProvider(Context context, String name) {
|
||||||
{
|
return mMainThread.acquireExistingProvider(context, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean releaseProvider(IContentProvider provider) {
|
||||||
return mMainThread.releaseProvider(provider);
|
return mMainThread.releaseProvider(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -313,6 +313,8 @@ public interface IActivityManager extends IInterface {
|
|||||||
|
|
||||||
public void crashApplication(int uid, int initialPid, String packageName,
|
public void crashApplication(int uid, int initialPid, String packageName,
|
||||||
String message) throws RemoteException;
|
String message) throws RemoteException;
|
||||||
|
|
||||||
|
public String getProviderMimeType(Uri uri) throws RemoteException;
|
||||||
|
|
||||||
public IBinder newUriPermissionOwner(String name) throws RemoteException;
|
public IBinder newUriPermissionOwner(String name) throws RemoteException;
|
||||||
public void grantUriPermissionFromOwner(IBinder owner, int fromUid, String targetPkg,
|
public void grantUriPermissionFromOwner(IBinder owner, int fromUid, String targetPkg,
|
||||||
@@ -526,7 +528,8 @@ public interface IActivityManager extends IInterface {
|
|||||||
int SET_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+111;
|
int SET_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+111;
|
||||||
int IS_TOP_ACTIVITY_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+112;
|
int IS_TOP_ACTIVITY_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+112;
|
||||||
int CRASH_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+113;
|
int CRASH_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+113;
|
||||||
int NEW_URI_PERMISSION_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+114;
|
int GET_PROVIDER_MIME_TYPE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+114;
|
||||||
int GRANT_URI_PERMISSION_FROM_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+115;
|
int NEW_URI_PERMISSION_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+115;
|
||||||
int REVOKE_URI_PERMISSION_FROM_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+116;
|
int GRANT_URI_PERMISSION_FROM_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+116;
|
||||||
|
int REVOKE_URI_PERMISSION_FROM_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+117;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -544,6 +544,12 @@ public abstract class ContentProvider implements ComponentCallbacks {
|
|||||||
* <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
|
* <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
|
||||||
* Processes and Threads</a>.
|
* Processes and Threads</a>.
|
||||||
*
|
*
|
||||||
|
* <p>Note that there are no permissions needed for an application to
|
||||||
|
* access this information; if your content provider requires read and/or
|
||||||
|
* write permissions, or is not exported, all applications can still call
|
||||||
|
* this method regardless of their access permissions. This allows them
|
||||||
|
* to retrieve the MIME type for a URI when dispatching intents.
|
||||||
|
*
|
||||||
* @param uri the URI to query.
|
* @param uri the URI to query.
|
||||||
* @return a MIME type string, or null if there is no type.
|
* @return a MIME type string, or null if there is no type.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package android.content;
|
package android.content;
|
||||||
|
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
|
import android.app.ActivityManagerNative;
|
||||||
import android.app.ActivityThread;
|
import android.app.ActivityThread;
|
||||||
import android.app.AppGlobals;
|
import android.app.AppGlobals;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
@@ -176,6 +177,12 @@ public abstract class ContentResolver {
|
|||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
protected abstract IContentProvider acquireProvider(Context c, String name);
|
protected abstract IContentProvider acquireProvider(Context c, String name);
|
||||||
|
/** Providing a default implementation of this, to avoid having to change
|
||||||
|
* a lot of other things, but implementations of ContentResolver should
|
||||||
|
* implement it. @hide */
|
||||||
|
protected IContentProvider acquireExistingProvider(Context c, String name) {
|
||||||
|
return acquireProvider(c, name);
|
||||||
|
}
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public abstract boolean releaseProvider(IContentProvider icp);
|
public abstract boolean releaseProvider(IContentProvider icp);
|
||||||
|
|
||||||
@@ -186,20 +193,29 @@ public abstract class ContentResolver {
|
|||||||
* using the content:// scheme.
|
* using the content:// scheme.
|
||||||
* @return A MIME type for the content, or null if the URL is invalid or the type is unknown
|
* @return A MIME type for the content, or null if the URL is invalid or the type is unknown
|
||||||
*/
|
*/
|
||||||
public final String getType(Uri url)
|
public final String getType(Uri url) {
|
||||||
{
|
IContentProvider provider = acquireExistingProvider(url);
|
||||||
IContentProvider provider = acquireProvider(url);
|
if (provider != null) {
|
||||||
if (provider == null) {
|
try {
|
||||||
|
return provider.getType(url);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
return null;
|
||||||
|
} catch (java.lang.Exception e) {
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
releaseProvider(provider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SCHEME_CONTENT.equals(url.getScheme())) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return provider.getType(url);
|
String type = ActivityManagerNative.getDefault().getProviderMimeType(url);
|
||||||
|
return type;
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
return null;
|
return null;
|
||||||
} catch (java.lang.Exception e) {
|
|
||||||
return null;
|
|
||||||
} finally {
|
|
||||||
releaseProvider(provider);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -717,14 +733,13 @@ public abstract class ContentResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the content provider for the given content URI..
|
* Returns the content provider for the given content URI.
|
||||||
*
|
*
|
||||||
* @param uri The URI to a content provider
|
* @param uri The URI to a content provider
|
||||||
* @return The ContentProvider for the given URI, or null if no content provider is found.
|
* @return The ContentProvider for the given URI, or null if no content provider is found.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public final IContentProvider acquireProvider(Uri uri)
|
public final IContentProvider acquireProvider(Uri uri) {
|
||||||
{
|
|
||||||
if (!SCHEME_CONTENT.equals(uri.getScheme())) {
|
if (!SCHEME_CONTENT.equals(uri.getScheme())) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -735,6 +750,25 @@ public abstract class ContentResolver {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the content provider for the given content URI if the process
|
||||||
|
* already has a reference on it.
|
||||||
|
*
|
||||||
|
* @param uri The URI to a content provider
|
||||||
|
* @return The ContentProvider for the given URI, or null if no content provider is found.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public final IContentProvider acquireExistingProvider(Uri uri) {
|
||||||
|
if (!SCHEME_CONTENT.equals(uri.getScheme())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String auth = uri.getAuthority();
|
||||||
|
if (auth != null) {
|
||||||
|
return acquireExistingProvider(mContext, uri.getAuthority());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5595,6 +5595,38 @@ public final class ActivityManagerService extends ActivityManagerNative
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows app to retrieve the MIME type of a URI without having permission
|
||||||
|
* to access its content provider.
|
||||||
|
*
|
||||||
|
* CTS tests for this functionality can be run with "runtest cts-appsecurity".
|
||||||
|
*
|
||||||
|
* Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
|
||||||
|
* src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
|
||||||
|
*/
|
||||||
|
public String getProviderMimeType(Uri uri) {
|
||||||
|
final String name = uri.getAuthority();
|
||||||
|
final long ident = Binder.clearCallingIdentity();
|
||||||
|
ContentProviderHolder holder = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
holder = getContentProviderExternal(name);
|
||||||
|
if (holder != null) {
|
||||||
|
return holder.provider.getType(uri);
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.w(TAG, "Content provider dead retrieving " + uri, e);
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
if (holder != null) {
|
||||||
|
removeContentProviderExternal(name);
|
||||||
|
}
|
||||||
|
Binder.restoreCallingIdentity(ident);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// =========================================================
|
// =========================================================
|
||||||
// GLOBAL MANAGEMENT
|
// GLOBAL MANAGEMENT
|
||||||
// =========================================================
|
// =========================================================
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ import java.util.HashSet;
|
|||||||
*
|
*
|
||||||
* CTS tests for this functionality can be run with "runtest cts-appsecurity".
|
* CTS tests for this functionality can be run with "runtest cts-appsecurity".
|
||||||
*
|
*
|
||||||
* Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert
|
* Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
|
||||||
* /src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
|
* src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
|
||||||
*/
|
*/
|
||||||
class UriPermission {
|
class UriPermission {
|
||||||
final int uid;
|
final int uid;
|
||||||
|
|||||||
@@ -75,6 +75,12 @@ public class MockContentResolver extends ContentResolver {
|
|||||||
/** @hide */
|
/** @hide */
|
||||||
@Override
|
@Override
|
||||||
protected IContentProvider acquireProvider(Context context, String name) {
|
protected IContentProvider acquireProvider(Context context, String name) {
|
||||||
|
return acquireExistingProvider(context, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
@Override
|
||||||
|
protected IContentProvider acquireExistingProvider(Context context, String name) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Gets the content provider from the local map
|
* Gets the content provider from the local map
|
||||||
|
|||||||
@@ -42,6 +42,12 @@ public class BridgeContentResolver extends ContentResolver {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IContentProvider acquireExistingProvider(Context c, String name) {
|
||||||
|
// ignore
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean releaseProvider(IContentProvider icp) {
|
public boolean releaseProvider(IContentProvider icp) {
|
||||||
// ignore
|
// ignore
|
||||||
|
|||||||
Reference in New Issue
Block a user