Skip to content

Commit

Permalink
Discourage use of "_data" column.
Browse files Browse the repository at this point in the history
Moving forward, all client file access really needs to be going
through explicit APIs like openFileDescriptor(), since that allows
the provider to better protect its underlying files.

This change also changes several classes to use the AutoClosable
pattern, which enables try-with-resources usage.  Older release()
methods are deprecated in favor of close().

Uniformly apply CloseGuard across several classes, using
AtomicBoolean to avoid double-freeing, and fix several resource
leaks and bugs related to MediaScanner allocation.  Switch
MediaScanner and friends to use public API instead of raw AIDL calls.

Bug: 22958127
Change-Id: Id722379f72c9e4b80d8b72550d7ce90e5e2bc786
  • Loading branch information
jsharkey committed Jan 6, 2016
1 parent 6a40ac6 commit 60cfad8
Show file tree
Hide file tree
Showing 14 changed files with 396 additions and 282 deletions.
12 changes: 7 additions & 5 deletions api/current.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4228,7 +4228,7 @@ package android.app {
field public static final java.lang.String COLUMN_DESCRIPTION = "description";
field public static final java.lang.String COLUMN_ID = "_id";
field public static final java.lang.String COLUMN_LAST_MODIFIED_TIMESTAMP = "last_modified_timestamp";
field public static final java.lang.String COLUMN_LOCAL_FILENAME = "local_filename";
field public static final deprecated java.lang.String COLUMN_LOCAL_FILENAME = "local_filename";
field public static final java.lang.String COLUMN_LOCAL_URI = "local_uri";
field public static final java.lang.String COLUMN_MEDIAPROVIDER_URI = "mediaprovider_uri";
field public static final java.lang.String COLUMN_MEDIA_TYPE = "media_type";
Expand Down Expand Up @@ -7568,11 +7568,12 @@ package android.content {
method public abstract void writeDataToPipe(android.os.ParcelFileDescriptor, android.net.Uri, java.lang.String, android.os.Bundle, T);
}

public class ContentProviderClient {
public class ContentProviderClient implements java.lang.AutoCloseable {
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 void close();
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;
Expand All @@ -7586,7 +7587,7 @@ package android.content {
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
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 deprecated 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;
}
Expand Down Expand Up @@ -10844,7 +10845,7 @@ package android.drm {
field public final int statusCode;
}

public class DrmManagerClient {
public class DrmManagerClient implements java.lang.AutoCloseable {
ctor public DrmManagerClient(android.content.Context);
method public android.drm.DrmInfo acquireDrmInfo(android.drm.DrmInfoRequest);
method public int acquireRights(android.drm.DrmInfoRequest);
Expand All @@ -10854,6 +10855,7 @@ package android.drm {
method public int checkRightsStatus(android.net.Uri);
method public int checkRightsStatus(java.lang.String, int);
method public int checkRightsStatus(android.net.Uri, int);
method public void close();
method public android.drm.DrmConvertedStatus closeConvertSession(int);
method public android.drm.DrmConvertedStatus convertData(int, byte[]);
method public java.lang.String[] getAvailableDrmEngines();
Expand All @@ -10867,7 +10869,7 @@ package android.drm {
method public java.lang.String getOriginalMimeType(android.net.Uri);
method public int openConvertSession(java.lang.String);
method public int processDrmInfo(android.drm.DrmInfo);
method public void release();
method public deprecated void release();
method public int removeAllRights();
method public int removeRights(java.lang.String);
method public int removeRights(android.net.Uri);
Expand Down
12 changes: 7 additions & 5 deletions api/system-current.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4348,7 +4348,7 @@ package android.app {
field public static final java.lang.String COLUMN_DESCRIPTION = "description";
field public static final java.lang.String COLUMN_ID = "_id";
field public static final java.lang.String COLUMN_LAST_MODIFIED_TIMESTAMP = "last_modified_timestamp";
field public static final java.lang.String COLUMN_LOCAL_FILENAME = "local_filename";
field public static final deprecated java.lang.String COLUMN_LOCAL_FILENAME = "local_filename";
field public static final java.lang.String COLUMN_LOCAL_URI = "local_uri";
field public static final java.lang.String COLUMN_MEDIAPROVIDER_URI = "mediaprovider_uri";
field public static final java.lang.String COLUMN_MEDIA_TYPE = "media_type";
Expand Down Expand Up @@ -7811,11 +7811,12 @@ package android.content {
method public abstract void writeDataToPipe(android.os.ParcelFileDescriptor, android.net.Uri, java.lang.String, android.os.Bundle, T);
}

public class ContentProviderClient {
public class ContentProviderClient implements java.lang.AutoCloseable {
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 void close();
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;
Expand All @@ -7829,7 +7830,7 @@ package android.content {
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
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 deprecated 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;
}
Expand Down Expand Up @@ -11198,7 +11199,7 @@ package android.drm {
field public final int statusCode;
}

public class DrmManagerClient {
public class DrmManagerClient implements java.lang.AutoCloseable {
ctor public DrmManagerClient(android.content.Context);
method public android.drm.DrmInfo acquireDrmInfo(android.drm.DrmInfoRequest);
method public int acquireRights(android.drm.DrmInfoRequest);
Expand All @@ -11208,6 +11209,7 @@ package android.drm {
method public int checkRightsStatus(android.net.Uri);
method public int checkRightsStatus(java.lang.String, int);
method public int checkRightsStatus(android.net.Uri, int);
method public void close();
method public android.drm.DrmConvertedStatus closeConvertSession(int);
method public android.drm.DrmConvertedStatus convertData(int, byte[]);
method public java.lang.String[] getAvailableDrmEngines();
Expand All @@ -11221,7 +11223,7 @@ package android.drm {
method public java.lang.String getOriginalMimeType(android.net.Uri);
method public int openConvertSession(java.lang.String);
method public int processDrmInfo(android.drm.DrmInfo);
method public void release();
method public deprecated void release();
method public int removeAllRights();
method public int removeRights(java.lang.String);
method public int removeRights(android.net.Uri);
Expand Down
12 changes: 7 additions & 5 deletions api/test-current.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4228,7 +4228,7 @@ package android.app {
field public static final java.lang.String COLUMN_DESCRIPTION = "description";
field public static final java.lang.String COLUMN_ID = "_id";
field public static final java.lang.String COLUMN_LAST_MODIFIED_TIMESTAMP = "last_modified_timestamp";
field public static final java.lang.String COLUMN_LOCAL_FILENAME = "local_filename";
field public static final deprecated java.lang.String COLUMN_LOCAL_FILENAME = "local_filename";
field public static final java.lang.String COLUMN_LOCAL_URI = "local_uri";
field public static final java.lang.String COLUMN_MEDIAPROVIDER_URI = "mediaprovider_uri";
field public static final java.lang.String COLUMN_MEDIA_TYPE = "media_type";
Expand Down Expand Up @@ -7568,11 +7568,12 @@ package android.content {
method public abstract void writeDataToPipe(android.os.ParcelFileDescriptor, android.net.Uri, java.lang.String, android.os.Bundle, T);
}

public class ContentProviderClient {
public class ContentProviderClient implements java.lang.AutoCloseable {
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 void close();
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;
Expand All @@ -7586,7 +7587,7 @@ package android.content {
method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle, android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
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 deprecated 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;
}
Expand Down Expand Up @@ -10844,7 +10845,7 @@ package android.drm {
field public final int statusCode;
}

public class DrmManagerClient {
public class DrmManagerClient implements java.lang.AutoCloseable {
ctor public DrmManagerClient(android.content.Context);
method public android.drm.DrmInfo acquireDrmInfo(android.drm.DrmInfoRequest);
method public int acquireRights(android.drm.DrmInfoRequest);
Expand All @@ -10854,6 +10855,7 @@ package android.drm {
method public int checkRightsStatus(android.net.Uri);
method public int checkRightsStatus(java.lang.String, int);
method public int checkRightsStatus(android.net.Uri, int);
method public void close();
method public android.drm.DrmConvertedStatus closeConvertSession(int);
method public android.drm.DrmConvertedStatus convertData(int, byte[]);
method public java.lang.String[] getAvailableDrmEngines();
Expand All @@ -10867,7 +10869,7 @@ package android.drm {
method public java.lang.String getOriginalMimeType(android.net.Uri);
method public int openConvertSession(java.lang.String);
method public int processDrmInfo(android.drm.DrmInfo);
method public void release();
method public deprecated void release();
method public int removeAllRights();
method public int removeRights(java.lang.String);
method public int removeRights(android.net.Uri);
Expand Down
48 changes: 37 additions & 11 deletions core/java/android/app/DownloadManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import android.net.ConnectivityManager;
import android.net.NetworkPolicyManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.provider.Downloads;
Expand Down Expand Up @@ -105,8 +106,17 @@ public class DownloadManager {
public final static String COLUMN_LOCAL_URI = "local_uri";

/**
* The pathname of the file where the download is stored.
* Path to the downloaded file on disk.
* <p>
* Note that apps may not have filesystem permissions to directly access
* this path. Instead of trying to open this path directly, apps should use
* {@link ContentResolver#openFileDescriptor(Uri, String)} to gain access.
*
* @deprecated apps should transition to using
* {@link ContentResolver#openFileDescriptor(Uri, String)}
* instead.
*/
@Deprecated
public final static String COLUMN_LOCAL_FILENAME = "local_filename";

/**
Expand Down Expand Up @@ -908,16 +918,19 @@ private String statusClause(String operator, int value) {
}
}

private ContentResolver mResolver;
private String mPackageName;
private final ContentResolver mResolver;
private final String mPackageName;
private final int mTargetSdkVersion;

private Uri mBaseUri = Downloads.Impl.CONTENT_URI;

/**
* @hide
*/
public DownloadManager(ContentResolver resolver, String packageName) {
mResolver = resolver;
mPackageName = packageName;
public DownloadManager(Context context) {
mResolver = context.getContentResolver();
mPackageName = context.getPackageName();
mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
}

/**
Expand Down Expand Up @@ -997,7 +1010,7 @@ public Cursor query(Query query) {
if (underlyingCursor == null) {
return null;
}
return new CursorTranslator(underlyingCursor, mBaseUri);
return new CursorTranslator(underlyingCursor, mBaseUri, mTargetSdkVersion);
}

/**
Expand Down Expand Up @@ -1265,11 +1278,13 @@ static String[] getWhereArgsForIds(long[] ids) {
* underlying data.
*/
private static class CursorTranslator extends CursorWrapper {
private Uri mBaseUri;
private final Uri mBaseUri;
private final int mTargetSdkVersion;

public CursorTranslator(Cursor cursor, Uri baseUri) {
public CursorTranslator(Cursor cursor, Uri baseUri, int targetSdkVersion) {
super(cursor);
mBaseUri = baseUri;
mTargetSdkVersion = targetSdkVersion;
}

@Override
Expand All @@ -1290,8 +1305,19 @@ public long getLong(int columnIndex) {

@Override
public String getString(int columnIndex) {
return (getColumnName(columnIndex).equals(COLUMN_LOCAL_URI)) ? getLocalUri() :
super.getString(columnIndex);
final String columnName = getColumnName(columnIndex);
switch (columnName) {
case COLUMN_LOCAL_URI:
return getLocalUri();
case COLUMN_LOCAL_FILENAME:
if (mTargetSdkVersion >= Build.VERSION_CODES.N) {
throw new IllegalArgumentException(
"COLUMN_LOCAL_FILENAME is deprecated;"
+ " use ContentResolver.openFileDescriptor() instead");
}
default:
return super.getString(columnIndex);
}
}

private String getLocalUri() {
Expand Down
2 changes: 1 addition & 1 deletion core/java/android/app/SystemServiceRegistry.java
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ public DevicePolicyManager createService(ContextImpl ctx) {
new CachedServiceFetcher<DownloadManager>() {
@Override
public DownloadManager createService(ContextImpl ctx) {
return new DownloadManager(ctx.getContentResolver(), ctx.getPackageName());
return new DownloadManager(ctx);
}});

registerService(Context.BATTERY_SERVICE, BatteryManager.class,
Expand Down
Loading

0 comments on commit 60cfad8

Please sign in to comment.