Loading api/current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -5623,6 +5623,7 @@ package android.content { method public void attachInfo(android.content.Context, android.content.pm.ProviderInfo); method public int bulkInsert(android.net.Uri, android.content.ContentValues[]); method public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle); method public android.net.Uri canonicalize(android.net.Uri); method public abstract int delete(android.net.Uri, java.lang.String, java.lang.String[]); method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]); method public final java.lang.String getCallingPackage(); Loading Loading @@ -5652,6 +5653,7 @@ package android.content { method protected final void setReadPermission(java.lang.String); method protected final void setWritePermission(java.lang.String); method public void shutdown(); method public android.net.Uri uncanonicalize(android.net.Uri); method public abstract int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]); } Loading @@ -5663,6 +5665,7 @@ package android.content { method public android.content.ContentProviderResult[] applyBatch(java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException; method public int bulkInsert(android.net.Uri, android.content.ContentValues[]) throws android.os.RemoteException; method public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle) throws android.os.RemoteException; method public final android.net.Uri canonicalize(android.net.Uri) throws android.os.RemoteException; method public int delete(android.net.Uri, java.lang.String, java.lang.String[]) throws android.os.RemoteException; method public android.content.ContentProvider getLocalContentProvider(); method public java.lang.String[] getStreamTypes(android.net.Uri, java.lang.String) throws android.os.RemoteException; Loading @@ -5677,6 +5680,7 @@ package android.content { method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String) throws android.os.RemoteException; method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal) throws android.os.RemoteException; method public boolean release(); method public final android.net.Uri uncanonicalize(android.net.Uri) throws android.os.RemoteException; method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]) throws android.os.RemoteException; } Loading Loading @@ -5742,6 +5746,7 @@ package android.content { method public final android.os.Bundle call(android.net.Uri, java.lang.String, java.lang.String, android.os.Bundle); method public deprecated void cancelSync(android.net.Uri); method public static void cancelSync(android.accounts.Account, java.lang.String); method public final android.net.Uri canonicalize(android.net.Uri); 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(); Loading Loading @@ -5779,6 +5784,7 @@ package android.content { method public static void setMasterSyncAutomatically(boolean); method public static void setSyncAutomatically(android.accounts.Account, java.lang.String, boolean); method public deprecated void startSync(android.net.Uri, android.os.Bundle); method public final android.net.Uri uncanonicalize(android.net.Uri); method public final void unregisterContentObserver(android.database.ContentObserver); method public final int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]); method public static void validateSyncExtrasBundle(android.os.Bundle); core/java/android/content/ContentProvider.java +77 −1 Original line number Diff line number Diff line Loading @@ -348,10 +348,36 @@ public abstract class ContentProvider implements ComponentCallbacks2 { } @Override public ICancellationSignal createCancellationSignal() throws RemoteException { public ICancellationSignal createCancellationSignal() { return CancellationSignal.createTransport(); } @Override public Uri canonicalize(String callingPkg, Uri uri) { if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { return null; } mCallingPackage.set(callingPkg); try { return ContentProvider.this.canonicalize(uri); } finally { mCallingPackage.set(null); } } @Override public Uri uncanonicalize(String callingPkg, Uri uri) { if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { return null; } mCallingPackage.set(callingPkg); try { return ContentProvider.this.uncanonicalize(uri); } finally { mCallingPackage.set(null); } } private void enforceFilePermission(String callingPkg, Uri uri, String mode) throws FileNotFoundException, SecurityException { if (mode != null && mode.indexOf('w') != -1) { Loading Loading @@ -840,6 +866,56 @@ public abstract class ContentProvider implements ComponentCallbacks2 { */ public abstract String getType(Uri uri); /** * Implement this to support canonicalization of URIs that refer to your * content provider. A canonical URI is one that can be transported across * devices, backup/restore, and other contexts, and still be able to refer * to the same data item. Typically this is implemented by adding query * params to the URI allowing the content provider to verify that an incoming * canonical URI references the same data as it was originally intended for and, * if it doesn't, to find that data (if it exists) in the current environment. * * <p>For example, if the content provider holds people and a normal URI in it * is created with a row index into that people database, the cananical representation * may have an additional query param at the end which specifies the name of the * person it is intended for. Later calls into the provider with that URI will look * up the row of that URI's base index and, if it doesn't match or its entry's * name doesn't match the name in the query param, perform a query on its database * to find the correct row to operate on.</p> * * <p>If you implement support for canonical URIs, <b>all</b> incoming calls with * URIs (including this one) must perform this verification and recovery of any * canonical URIs they receive. In addition, you must also implement * {@link #uncanonicalize} to strip the canonicalization of any of these URIs.</p> * * <p>The default implementation of this method returns null, indicating that * canonical URIs are not supported.</p> * * @param url The Uri to canonicalize. * * @return Return the canonical representation of <var>url</var>, or null if * canonicalization of that Uri is not supported. */ public Uri canonicalize(Uri url) { return null; } /** * Remove canonicalization from canonical URIs previously returned by * {@link #canonicalize}. For example, if your implementation is to add * a query param to canonicalize a URI, this method can simply trip any * query params on the URI. The default implementation always returns the * same <var>url</var> that was passed in. * * @param url The Uri to remove any canonicalization from. * * @return Return the non-canonical representation of <var>url</var>, or return * the <var>url</var> as-is if there is nothing to do. Never return null. */ public Uri uncanonicalize(Uri url) { return url; } /** * @hide * Implementation when a caller has performed an insert on the content Loading core/java/android/content/ContentProviderClient.java +24 −0 Original line number Diff line number Diff line Loading @@ -110,6 +110,30 @@ public class ContentProviderClient { } } /** See {@link ContentProvider#canonicalize} */ public final Uri canonicalize(Uri url) throws RemoteException { try { return mContentProvider.canonicalize(mPackageName, url); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); } throw e; } } /** See {@link ContentProvider#uncanonicalize} */ public final Uri uncanonicalize(Uri url) throws RemoteException { try { return mContentProvider.uncanonicalize(mPackageName, url); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); } throw e; } } /** See {@link ContentProvider#insert ContentProvider.insert} */ public Uri insert(Uri url, ContentValues initialValues) throws RemoteException { Loading core/java/android/content/ContentProviderNative.java +65 −0 Original line number Diff line number Diff line Loading @@ -323,6 +323,30 @@ abstract public class ContentProviderNative extends Binder implements IContentPr reply.writeStrongBinder(cancellationSignal.asBinder()); return true; } case CANONICALIZE_TRANSACTION: { data.enforceInterface(IContentProvider.descriptor); String callingPkg = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); Uri out = canonicalize(callingPkg, url); reply.writeNoException(); Uri.writeToParcel(reply, out); return true; } case UNCANONICALIZE_TRANSACTION: { data.enforceInterface(IContentProvider.descriptor); String callingPkg = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); Uri out = uncanonicalize(callingPkg, url); reply.writeNoException(); Uri.writeToParcel(reply, out); return true; } } } catch (Exception e) { DatabaseUtils.writeExceptionToParcel(reply, e); Loading Loading @@ -685,5 +709,46 @@ final class ContentProviderProxy implements IContentProvider } } public Uri canonicalize(String callingPkg, Uri url) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); data.writeString(callingPkg); url.writeToParcel(data, 0); mRemote.transact(IContentProvider.CANONICALIZE_TRANSACTION, data, reply, 0); DatabaseUtils.readExceptionFromParcel(reply); Uri out = Uri.CREATOR.createFromParcel(reply); return out; } finally { data.recycle(); reply.recycle(); } } public Uri uncanonicalize(String callingPkg, Uri url) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); data.writeString(callingPkg); url.writeToParcel(data, 0); mRemote.transact(IContentProvider.UNCANONICALIZE_TRANSACTION, data, reply, 0); DatabaseUtils.readExceptionFromParcel(reply); Uri out = Uri.CREATOR.createFromParcel(reply); return out; } finally { data.recycle(); reply.recycle(); } } private IBinder mRemote; } core/java/android/content/ContentResolver.java +80 −0 Original line number Diff line number Diff line Loading @@ -496,6 +496,86 @@ public abstract class ContentResolver { } } /** * Transform the given <var>url</var> to a canonical representation of * its referenced resource, which can be used across devices, persisted, * backed up and restored, etc. The returned Uri is still a fully capable * Uri for use with its content provider, allowing you to do all of the * same content provider operations as with the original Uri -- * {@link #query}, {@link #openInputStream(android.net.Uri)}, etc. The * only difference in behavior between the original and new Uris is that * the content provider may need to do some additional work at each call * using it to resolve it to the correct resource, especially if the * canonical Uri has been moved to a different environment. * * <p>If you are moving a canonical Uri between environments, you should * perform another call to {@link #canonicalize} with that original Uri to * re-canonicalize it for the current environment. Alternatively, you may * want to use {@link #uncanonicalize} to transform it to a non-canonical * Uri that works only in the current environment but potentially more * efficiently than the canonical representation.</p> * * @param url The {@link Uri} that is to be transformed to a canonical * representation. Like all resolver calls, the input can be either * a non-canonical or canonical Uri. * * @return Returns the official canonical representation of <var>url</var>, * or null if the content provider does not support a canonical representation * of the given Uri. Many providers may not support canonicalization of some * or all of their Uris. * * @see #uncanonicalize */ public final Uri canonicalize(Uri url) { IContentProvider provider = acquireProvider(url); if (provider == null) { return null; } try { return provider.canonicalize(mPackageName, url); } catch (RemoteException e) { // Arbitrary and not worth documenting, as Activity // Manager will kill this process shortly anyway. return null; } finally { releaseProvider(provider); } } /** * Given a canonical Uri previously generated by {@link #canonicalize}, convert * it to its local non-canonical form. This can be useful in some cases where * you know that you will only be using the Uri in the current environment and * want to avoid any possible overhead when using it with the content * provider. * * @param url The canonical {@link Uri} that is to be convered back to its * non-canonical form. * * @return Returns the non-canonical representation of <var>url</var>. This * function never returns null; if there is no conversion to be done, it returns * the same Uri that was provided. * * @see #canonicalize */ public final Uri uncanonicalize(Uri url) { IContentProvider provider = acquireProvider(url); if (provider == null) { return null; } try { return provider.uncanonicalize(mPackageName, url); } catch (RemoteException e) { // Arbitrary and not worth documenting, as Activity // Manager will kill this process shortly anyway. return null; } finally { releaseProvider(provider); } } /** * Open a stream on to the content associated with a content URI. If there * is no data associated with the URI, FileNotFoundException is thrown. Loading Loading
api/current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -5623,6 +5623,7 @@ package android.content { method public void attachInfo(android.content.Context, android.content.pm.ProviderInfo); method public int bulkInsert(android.net.Uri, android.content.ContentValues[]); method public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle); method public android.net.Uri canonicalize(android.net.Uri); method public abstract int delete(android.net.Uri, java.lang.String, java.lang.String[]); method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]); method public final java.lang.String getCallingPackage(); Loading Loading @@ -5652,6 +5653,7 @@ package android.content { method protected final void setReadPermission(java.lang.String); method protected final void setWritePermission(java.lang.String); method public void shutdown(); method public android.net.Uri uncanonicalize(android.net.Uri); method public abstract int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]); } Loading @@ -5663,6 +5665,7 @@ package android.content { method public android.content.ContentProviderResult[] applyBatch(java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException; method public int bulkInsert(android.net.Uri, android.content.ContentValues[]) throws android.os.RemoteException; method public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle) throws android.os.RemoteException; method public final android.net.Uri canonicalize(android.net.Uri) throws android.os.RemoteException; method public int delete(android.net.Uri, java.lang.String, java.lang.String[]) throws android.os.RemoteException; method public android.content.ContentProvider getLocalContentProvider(); method public java.lang.String[] getStreamTypes(android.net.Uri, java.lang.String) throws android.os.RemoteException; Loading @@ -5677,6 +5680,7 @@ package android.content { method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String) throws android.os.RemoteException; method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal) throws android.os.RemoteException; method public boolean release(); method public final android.net.Uri uncanonicalize(android.net.Uri) throws android.os.RemoteException; method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]) throws android.os.RemoteException; } Loading Loading @@ -5742,6 +5746,7 @@ package android.content { method public final android.os.Bundle call(android.net.Uri, java.lang.String, java.lang.String, android.os.Bundle); method public deprecated void cancelSync(android.net.Uri); method public static void cancelSync(android.accounts.Account, java.lang.String); method public final android.net.Uri canonicalize(android.net.Uri); 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(); Loading Loading @@ -5779,6 +5784,7 @@ package android.content { method public static void setMasterSyncAutomatically(boolean); method public static void setSyncAutomatically(android.accounts.Account, java.lang.String, boolean); method public deprecated void startSync(android.net.Uri, android.os.Bundle); method public final android.net.Uri uncanonicalize(android.net.Uri); method public final void unregisterContentObserver(android.database.ContentObserver); method public final int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]); method public static void validateSyncExtrasBundle(android.os.Bundle);
core/java/android/content/ContentProvider.java +77 −1 Original line number Diff line number Diff line Loading @@ -348,10 +348,36 @@ public abstract class ContentProvider implements ComponentCallbacks2 { } @Override public ICancellationSignal createCancellationSignal() throws RemoteException { public ICancellationSignal createCancellationSignal() { return CancellationSignal.createTransport(); } @Override public Uri canonicalize(String callingPkg, Uri uri) { if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { return null; } mCallingPackage.set(callingPkg); try { return ContentProvider.this.canonicalize(uri); } finally { mCallingPackage.set(null); } } @Override public Uri uncanonicalize(String callingPkg, Uri uri) { if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { return null; } mCallingPackage.set(callingPkg); try { return ContentProvider.this.uncanonicalize(uri); } finally { mCallingPackage.set(null); } } private void enforceFilePermission(String callingPkg, Uri uri, String mode) throws FileNotFoundException, SecurityException { if (mode != null && mode.indexOf('w') != -1) { Loading Loading @@ -840,6 +866,56 @@ public abstract class ContentProvider implements ComponentCallbacks2 { */ public abstract String getType(Uri uri); /** * Implement this to support canonicalization of URIs that refer to your * content provider. A canonical URI is one that can be transported across * devices, backup/restore, and other contexts, and still be able to refer * to the same data item. Typically this is implemented by adding query * params to the URI allowing the content provider to verify that an incoming * canonical URI references the same data as it was originally intended for and, * if it doesn't, to find that data (if it exists) in the current environment. * * <p>For example, if the content provider holds people and a normal URI in it * is created with a row index into that people database, the cananical representation * may have an additional query param at the end which specifies the name of the * person it is intended for. Later calls into the provider with that URI will look * up the row of that URI's base index and, if it doesn't match or its entry's * name doesn't match the name in the query param, perform a query on its database * to find the correct row to operate on.</p> * * <p>If you implement support for canonical URIs, <b>all</b> incoming calls with * URIs (including this one) must perform this verification and recovery of any * canonical URIs they receive. In addition, you must also implement * {@link #uncanonicalize} to strip the canonicalization of any of these URIs.</p> * * <p>The default implementation of this method returns null, indicating that * canonical URIs are not supported.</p> * * @param url The Uri to canonicalize. * * @return Return the canonical representation of <var>url</var>, or null if * canonicalization of that Uri is not supported. */ public Uri canonicalize(Uri url) { return null; } /** * Remove canonicalization from canonical URIs previously returned by * {@link #canonicalize}. For example, if your implementation is to add * a query param to canonicalize a URI, this method can simply trip any * query params on the URI. The default implementation always returns the * same <var>url</var> that was passed in. * * @param url The Uri to remove any canonicalization from. * * @return Return the non-canonical representation of <var>url</var>, or return * the <var>url</var> as-is if there is nothing to do. Never return null. */ public Uri uncanonicalize(Uri url) { return url; } /** * @hide * Implementation when a caller has performed an insert on the content Loading
core/java/android/content/ContentProviderClient.java +24 −0 Original line number Diff line number Diff line Loading @@ -110,6 +110,30 @@ public class ContentProviderClient { } } /** See {@link ContentProvider#canonicalize} */ public final Uri canonicalize(Uri url) throws RemoteException { try { return mContentProvider.canonicalize(mPackageName, url); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); } throw e; } } /** See {@link ContentProvider#uncanonicalize} */ public final Uri uncanonicalize(Uri url) throws RemoteException { try { return mContentProvider.uncanonicalize(mPackageName, url); } catch (DeadObjectException e) { if (!mStable) { mContentResolver.unstableProviderDied(mContentProvider); } throw e; } } /** See {@link ContentProvider#insert ContentProvider.insert} */ public Uri insert(Uri url, ContentValues initialValues) throws RemoteException { Loading
core/java/android/content/ContentProviderNative.java +65 −0 Original line number Diff line number Diff line Loading @@ -323,6 +323,30 @@ abstract public class ContentProviderNative extends Binder implements IContentPr reply.writeStrongBinder(cancellationSignal.asBinder()); return true; } case CANONICALIZE_TRANSACTION: { data.enforceInterface(IContentProvider.descriptor); String callingPkg = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); Uri out = canonicalize(callingPkg, url); reply.writeNoException(); Uri.writeToParcel(reply, out); return true; } case UNCANONICALIZE_TRANSACTION: { data.enforceInterface(IContentProvider.descriptor); String callingPkg = data.readString(); Uri url = Uri.CREATOR.createFromParcel(data); Uri out = uncanonicalize(callingPkg, url); reply.writeNoException(); Uri.writeToParcel(reply, out); return true; } } } catch (Exception e) { DatabaseUtils.writeExceptionToParcel(reply, e); Loading Loading @@ -685,5 +709,46 @@ final class ContentProviderProxy implements IContentProvider } } public Uri canonicalize(String callingPkg, Uri url) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); data.writeString(callingPkg); url.writeToParcel(data, 0); mRemote.transact(IContentProvider.CANONICALIZE_TRANSACTION, data, reply, 0); DatabaseUtils.readExceptionFromParcel(reply); Uri out = Uri.CREATOR.createFromParcel(reply); return out; } finally { data.recycle(); reply.recycle(); } } public Uri uncanonicalize(String callingPkg, Uri url) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { data.writeInterfaceToken(IContentProvider.descriptor); data.writeString(callingPkg); url.writeToParcel(data, 0); mRemote.transact(IContentProvider.UNCANONICALIZE_TRANSACTION, data, reply, 0); DatabaseUtils.readExceptionFromParcel(reply); Uri out = Uri.CREATOR.createFromParcel(reply); return out; } finally { data.recycle(); reply.recycle(); } } private IBinder mRemote; }
core/java/android/content/ContentResolver.java +80 −0 Original line number Diff line number Diff line Loading @@ -496,6 +496,86 @@ public abstract class ContentResolver { } } /** * Transform the given <var>url</var> to a canonical representation of * its referenced resource, which can be used across devices, persisted, * backed up and restored, etc. The returned Uri is still a fully capable * Uri for use with its content provider, allowing you to do all of the * same content provider operations as with the original Uri -- * {@link #query}, {@link #openInputStream(android.net.Uri)}, etc. The * only difference in behavior between the original and new Uris is that * the content provider may need to do some additional work at each call * using it to resolve it to the correct resource, especially if the * canonical Uri has been moved to a different environment. * * <p>If you are moving a canonical Uri between environments, you should * perform another call to {@link #canonicalize} with that original Uri to * re-canonicalize it for the current environment. Alternatively, you may * want to use {@link #uncanonicalize} to transform it to a non-canonical * Uri that works only in the current environment but potentially more * efficiently than the canonical representation.</p> * * @param url The {@link Uri} that is to be transformed to a canonical * representation. Like all resolver calls, the input can be either * a non-canonical or canonical Uri. * * @return Returns the official canonical representation of <var>url</var>, * or null if the content provider does not support a canonical representation * of the given Uri. Many providers may not support canonicalization of some * or all of their Uris. * * @see #uncanonicalize */ public final Uri canonicalize(Uri url) { IContentProvider provider = acquireProvider(url); if (provider == null) { return null; } try { return provider.canonicalize(mPackageName, url); } catch (RemoteException e) { // Arbitrary and not worth documenting, as Activity // Manager will kill this process shortly anyway. return null; } finally { releaseProvider(provider); } } /** * Given a canonical Uri previously generated by {@link #canonicalize}, convert * it to its local non-canonical form. This can be useful in some cases where * you know that you will only be using the Uri in the current environment and * want to avoid any possible overhead when using it with the content * provider. * * @param url The canonical {@link Uri} that is to be convered back to its * non-canonical form. * * @return Returns the non-canonical representation of <var>url</var>. This * function never returns null; if there is no conversion to be done, it returns * the same Uri that was provided. * * @see #canonicalize */ public final Uri uncanonicalize(Uri url) { IContentProvider provider = acquireProvider(url); if (provider == null) { return null; } try { return provider.uncanonicalize(mPackageName, url); } catch (RemoteException e) { // Arbitrary and not worth documenting, as Activity // Manager will kill this process shortly anyway. return null; } finally { releaseProvider(provider); } } /** * Open a stream on to the content associated with a content URI. If there * is no data associated with the URI, FileNotFoundException is thrown. Loading