summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--legacy/src/com/android/providers/media/LegacyMediaProvider.java4
-rw-r--r--src/com/android/providers/media/DatabaseHelper.java22
-rw-r--r--src/com/android/providers/media/MediaProvider.java13
-rw-r--r--src/com/android/providers/media/MediaUpgradeReceiver.java3
-rw-r--r--src/com/android/providers/media/util/SQLiteQueryBuilder.java31
-rw-r--r--tests/src/com/android/providers/media/DatabaseHelperTest.java8
6 files changed, 69 insertions, 12 deletions
diff --git a/legacy/src/com/android/providers/media/LegacyMediaProvider.java b/legacy/src/com/android/providers/media/LegacyMediaProvider.java
index 488e72a8e..086f88c52 100644
--- a/legacy/src/com/android/providers/media/LegacyMediaProvider.java
+++ b/legacy/src/com/android/providers/media/LegacyMediaProvider.java
@@ -73,9 +73,9 @@ public class LegacyMediaProvider extends ContentProvider {
Logging.initPersistent(persistentDir);
mInternalDatabase = new DatabaseHelper(context, INTERNAL_DATABASE_NAME,
- true, false, true, null, null, null, null);
+ true, false, true, null, null, null, null, null);
mExternalDatabase = new DatabaseHelper(context, EXTERNAL_DATABASE_NAME,
- false, false, true, null, null, null, null);
+ false, false, true, null, null, null, null, null);
return true;
}
diff --git a/src/com/android/providers/media/DatabaseHelper.java b/src/com/android/providers/media/DatabaseHelper.java
index 20b64237b..5ad5340a9 100644
--- a/src/com/android/providers/media/DatabaseHelper.java
+++ b/src/com/android/providers/media/DatabaseHelper.java
@@ -75,6 +75,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.function.LongSupplier;
+import java.util.function.UnaryOperator;
import java.util.regex.Matcher;
/**
@@ -104,6 +105,7 @@ public class DatabaseHelper extends SQLiteOpenHelper implements AutoCloseable {
final @Nullable OnSchemaChangeListener mSchemaListener;
final @Nullable OnFilesChangeListener mFilesListener;
final @Nullable OnLegacyMigrationListener mMigrationListener;
+ final @Nullable UnaryOperator<String> mIdGenerator;
final Set<String> mFilterVolumeNames = new ArraySet<>();
long mScanStartTime;
long mScanStopTime;
@@ -135,9 +137,10 @@ public class DatabaseHelper extends SQLiteOpenHelper implements AutoCloseable {
@Nullable Class<? extends Annotation> columnAnnotation,
@Nullable OnSchemaChangeListener schemaListener,
@Nullable OnFilesChangeListener filesListener,
- @Nullable OnLegacyMigrationListener migrationListener) {
+ @Nullable OnLegacyMigrationListener migrationListener,
+ @Nullable UnaryOperator<String> idGenerator) {
this(context, name, getDatabaseVersion(context), internal, earlyUpgrade, legacyProvider,
- columnAnnotation, schemaListener, filesListener, migrationListener);
+ columnAnnotation, schemaListener, filesListener, migrationListener, idGenerator);
}
public DatabaseHelper(Context context, String name, int version,
@@ -145,7 +148,8 @@ public class DatabaseHelper extends SQLiteOpenHelper implements AutoCloseable {
@Nullable Class<? extends Annotation> columnAnnotation,
@Nullable OnSchemaChangeListener schemaListener,
@Nullable OnFilesChangeListener filesListener,
- @Nullable OnLegacyMigrationListener migrationListener) {
+ @Nullable OnLegacyMigrationListener migrationListener,
+ @Nullable UnaryOperator<String> idGenerator) {
super(context, name, null, version);
mContext = context;
mName = name;
@@ -158,6 +162,7 @@ public class DatabaseHelper extends SQLiteOpenHelper implements AutoCloseable {
mSchemaListener = schemaListener;
mFilesListener = filesListener;
mMigrationListener = migrationListener;
+ mIdGenerator = idGenerator;
// Configure default filters until we hear differently
if (mInternal) {
@@ -270,6 +275,17 @@ public class DatabaseHelper extends SQLiteOpenHelper implements AutoCloseable {
}
return null;
});
+ db.setCustomScalarFunction("_GET_ID", (arg) -> {
+ if (mIdGenerator != null && !mSchemaChanging) {
+ Trace.beginSection("_GET_ID");
+ try {
+ return mIdGenerator.apply(arg);
+ } finally {
+ Trace.endSection();
+ }
+ }
+ return null;
+ });
}
@Override
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index 9259e9430..f4cbe9775 100644
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -208,6 +208,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
+import java.util.function.UnaryOperator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -584,6 +585,14 @@ public class MediaProvider extends ContentProvider {
}
};
+ private final UnaryOperator<String> mIdGenerator = path -> {
+ final long rowId = mCallingIdentity.get().getDeletedRowId(path);
+ if (rowId != -1 && isFuseThread()) {
+ return String.valueOf(rowId);
+ }
+ return null;
+ };
+
private final OnLegacyMigrationListener mMigrationListener = new OnLegacyMigrationListener() {
@Override
public void onStarted(ContentProviderClient client, String volumeName) {
@@ -787,10 +796,10 @@ public class MediaProvider extends ContentProvider {
mInternalDatabase = new DatabaseHelper(context, INTERNAL_DATABASE_NAME,
true, false, mLegacyProvider, Column.class,
- Metrics::logSchemaChange, mFilesListener, mMigrationListener);
+ Metrics::logSchemaChange, mFilesListener, mMigrationListener, mIdGenerator);
mExternalDatabase = new DatabaseHelper(context, EXTERNAL_DATABASE_NAME,
false, false, mLegacyProvider, Column.class,
- Metrics::logSchemaChange, mFilesListener, mMigrationListener);
+ Metrics::logSchemaChange, mFilesListener, mMigrationListener, mIdGenerator);
final IntentFilter packageFilter = new IntentFilter();
packageFilter.setPriority(10);
diff --git a/src/com/android/providers/media/MediaUpgradeReceiver.java b/src/com/android/providers/media/MediaUpgradeReceiver.java
index dd99fc48d..932b20b31 100644
--- a/src/com/android/providers/media/MediaUpgradeReceiver.java
+++ b/src/com/android/providers/media/MediaUpgradeReceiver.java
@@ -69,7 +69,8 @@ public class MediaUpgradeReceiver extends BroadcastReceiver {
try {
DatabaseHelper helper = new DatabaseHelper(
context, file, MediaProvider.isInternalMediaDatabaseName(file),
- false, false, Column.class, Metrics::logSchemaChange, null, null);
+ false, false, Column.class, Metrics::logSchemaChange, null, null,
+ null);
db = helper.getWritableDatabase();
} catch (Throwable t) {
Log.wtf(TAG, "Error during upgrade of media db " + file, t);
diff --git a/src/com/android/providers/media/util/SQLiteQueryBuilder.java b/src/com/android/providers/media/util/SQLiteQueryBuilder.java
index 990457c24..da279aa18 100644
--- a/src/com/android/providers/media/util/SQLiteQueryBuilder.java
+++ b/src/com/android/providers/media/util/SQLiteQueryBuilder.java
@@ -74,6 +74,18 @@ public class SQLiteQueryBuilder {
private int mStrictFlags;
+ /**
+ * Raw SQL clause to obtain the value of {@link MediaColumns#_ID} from custom database function
+ * {@code _GET_ID} for INSERT operation.
+ */
+ private static final String GET_ID_FOR_INSERT_CLAUSE = "_GET_ID('%s')";
+
+ /**
+ * Raw SQL clause to obtain the value of {@link MediaColumns#_ID} from custom database function
+ * {@code _GET_ID} for UPDATE operation.
+ */
+ private static final String GET_ID_FOR_UPDATE_CLAUSE = "ifnull(_GET_ID('%s'), _id)";
+
public SQLiteQueryBuilder() {
mDistinct = false;
}
@@ -838,6 +850,11 @@ public class SQLiteQueryBuilder {
sql.append(',');
sql.append(MediaColumns.GENERATION_MODIFIED);
}
+ if (shouldAppendRowId(values)) {
+ sql.append(',');
+ sql.append(MediaColumns._ID);
+ }
+
sql.append(") VALUES (");
for (int i = 0; i < rawValues.size(); i++) {
if (i > 0) {
@@ -855,6 +872,10 @@ public class SQLiteQueryBuilder {
sql.append(DatabaseHelper.CURRENT_GENERATION_CLAUSE);
sql.append(')');
}
+ if (shouldAppendRowId(values)) {
+ sql.append(',');
+ sql.append(String.format(GET_ID_FOR_INSERT_CLAUSE, values.get(MediaColumns.DATA)));
+ }
sql.append(")");
return sql.toString();
}
@@ -893,6 +914,12 @@ public class SQLiteQueryBuilder {
sql.append(DatabaseHelper.CURRENT_GENERATION_CLAUSE);
sql.append(')');
}
+ if (shouldAppendRowId(values)) {
+ sql.append(',');
+ sql.append(MediaColumns._ID);
+ sql.append('=');
+ sql.append(String.format(GET_ID_FOR_UPDATE_CLAUSE, values.get(MediaColumns.DATA)));
+ }
final String where = computeWhere(selection);
appendClause(sql, " WHERE ", where);
@@ -1044,4 +1071,8 @@ public class SQLiteQueryBuilder {
return "(" + arg + ")";
}
}
+
+ private static boolean shouldAppendRowId(ContentValues values) {
+ return !values.containsKey(MediaColumns._ID) && values.containsKey(MediaColumns.DATA);
+ }
}
diff --git a/tests/src/com/android/providers/media/DatabaseHelperTest.java b/tests/src/com/android/providers/media/DatabaseHelperTest.java
index badff085e..114985440 100644
--- a/tests/src/com/android/providers/media/DatabaseHelperTest.java
+++ b/tests/src/com/android/providers/media/DatabaseHelperTest.java
@@ -426,7 +426,7 @@ public class DatabaseHelperTest {
private static class DatabaseHelperO extends DatabaseHelper {
public DatabaseHelperO(Context context, String name) {
super(context, name, DatabaseHelper.VERSION_O,
- false, false, true, Column.class, null, null, null);
+ false, false, true, Column.class, null, null, null, null);
}
@Override
@@ -443,7 +443,7 @@ public class DatabaseHelperTest {
private static class DatabaseHelperP extends DatabaseHelper {
public DatabaseHelperP(Context context, String name) {
super(context, name, DatabaseHelper.VERSION_P,
- false, false, true, Column.class, null, null, null);
+ false, false, true, Column.class, null, null, null, null);
}
@Override
@@ -460,7 +460,7 @@ public class DatabaseHelperTest {
private static class DatabaseHelperQ extends DatabaseHelper {
public DatabaseHelperQ(Context context, String name) {
super(context, name, DatabaseHelper.VERSION_Q,
- false, false, true, Column.class, null, null, null);
+ false, false, true, Column.class, null, null, null, null);
}
@Override
@@ -477,7 +477,7 @@ public class DatabaseHelperTest {
private static class DatabaseHelperR extends DatabaseHelper {
public DatabaseHelperR(Context context, String name) {
super(context, name, DatabaseHelper.VERSION_R,
- false, false, true, Column.class, null, null, null);
+ false, false, true, Column.class, null, null, null, null);
}
}