From bf8b367dd678419dda542346672b882cd58911b4 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Mon, 13 Jan 2020 21:39:15 -0700 Subject: Introduce "generation" to track mutations. Add generation numbers to the metadata for each media item. This is useful for apps that are attempting to quickly identify exactly which media items have changed since a previous point in time. Generation numbers are monotonically increasing over time, and can be safely arithmetically compared. Detecting media changes using generation numbers is more robust than using DATE_MODIFIED, since those values may change in unexpected ways when apps use File.setLastModified() or when the system clock is set incorrectly. This is implemented by ensuring that all mutations to go through our local SQLiteQueryBuilder, which then forces those mutations to always happen inside an active transaction. Then each time we create a transaction, we increment the generation counter, and force-copy the current generation into any mutation operations. This design also means that all mutations that should affect the generation counter must go through DatabaseHelper to ensure that the logic above is applied; there's mechanical refactoring across MediaProvider to accomplish this. Fix bug in getWritableDatabase() that could return a readable database. Fix bug in LegacyMediaProvider to create missing directories. Adjust logging script to enable log cleaner SQL from SQLQueryBuilder instead of noisy raw logs. Bug: 140248585 Test: atest --test-mapping packages/providers/MediaProvider Change-Id: If87f586e2340688ea1716682de20ee40c0d2b953 --- api/current.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/current.txt b/api/current.txt index 5ab1c0171c61..1492ede2bcf7 100644 --- a/api/current.txt +++ b/api/current.txt @@ -39183,6 +39183,7 @@ package android.provider { method @NonNull public static android.app.PendingIntent createWriteRequest(@NonNull android.content.ContentResolver, @NonNull java.util.Collection); method @Nullable public static android.net.Uri getDocumentUri(@NonNull android.content.Context, @NonNull android.net.Uri); method @NonNull public static java.util.Set getExternalVolumeNames(@NonNull android.content.Context); + method public static long getGeneration(@NonNull android.content.Context, @NonNull String); method public static android.net.Uri getMediaScannerUri(); method @Nullable public static android.net.Uri getMediaUri(@NonNull android.content.Context, @NonNull android.net.Uri); method @NonNull public static java.util.Set getRecentExternalVolumeNames(@NonNull android.content.Context); @@ -39493,6 +39494,7 @@ package android.provider { field public static final String DISPLAY_NAME = "_display_name"; field public static final String DOCUMENT_ID = "document_id"; field public static final String DURATION = "duration"; + field public static final String GENERATION = "generation"; field public static final String GENRE = "genre"; field public static final String HEIGHT = "height"; field public static final String INSTANCE_ID = "instance_id"; -- cgit v1.2.3-59-g8ed1b