Merge "Work on issue #10130785: Restore silence and vibrate settings..." into klp-dev

This commit is contained in:
Dianne Hackborn
2013-09-08 19:31:06 +00:00
committed by Android (Google) Code Review
8 changed files with 277 additions and 1 deletions

View File

@@ -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();
@@ -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[]);
}
@@ -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;
@@ -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;
}
@@ -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();
@@ -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);

View File

@@ -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) {
@@ -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

View File

@@ -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 {

View File

@@ -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);
@@ -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;
}

View File

@@ -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.

View File

@@ -59,6 +59,9 @@ public interface IContentProvider extends IInterface {
throws RemoteException;
public ICancellationSignal createCancellationSignal() throws RemoteException;
public Uri canonicalize(String callingPkg, Uri uri) throws RemoteException;
public Uri uncanonicalize(String callingPkg, Uri uri) throws RemoteException;
// Data interchange.
public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException;
public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri url, String mimeType,
@@ -80,4 +83,6 @@ public interface IContentProvider extends IInterface {
static final int GET_STREAM_TYPES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 21;
static final int OPEN_TYPED_ASSET_FILE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 22;
static final int CREATE_CANCELATION_SIGNAL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 23;
static final int CANONICALIZE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 24;
static final int UNCANONICALIZE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 25;
}

View File

@@ -137,6 +137,16 @@ public class MockContentProvider extends ContentProvider {
public ICancellationSignal createCancellationSignal() throws RemoteException {
return null;
}
@Override
public Uri canonicalize(String callingPkg, Uri uri) throws RemoteException {
return MockContentProvider.this.canonicalize(uri);
}
@Override
public Uri uncanonicalize(String callingPkg, Uri uri) throws RemoteException {
return MockContentProvider.this.uncanonicalize(uri);
}
}
private final InversionIContentProvider mIContentProvider = new InversionIContentProvider();

View File

@@ -114,4 +114,14 @@ public class MockIContentProvider implements IContentProvider {
public ICancellationSignal createCancellationSignal() throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
public Uri canonicalize(String callingPkg, Uri uri) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
public Uri uncanonicalize(String callingPkg, Uri uri) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
}