Merge "Add per-media-type logging for deletion" into mainline-prod
diff --git a/apex/framework/java/android/provider/MediaStore.java b/apex/framework/java/android/provider/MediaStore.java
index 91709f8..e49f338 100644
--- a/apex/framework/java/android/provider/MediaStore.java
+++ b/apex/framework/java/android/provider/MediaStore.java
@@ -1699,6 +1699,12 @@
public static final int MEDIA_TYPE_DOCUMENT = 6;
/**
+ * Constant indicating the count of {@link #MEDIA_TYPE} columns.
+ * @hide
+ */
+ public static final int MEDIA_TYPE_COUNT = 7;
+
+ /**
* Modifier of the database row
*
* Specifies the last modifying operation of the database row. This
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index 9e1efa5..f1902dc 100644
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -4706,6 +4706,7 @@
};
final boolean isFilesTable = qb.getTables().equals("files");
final LongSparseArray<String> deletedDownloadIds = new LongSparseArray<>();
+ final int[] countPerMediaType = new int[FileColumns.MEDIA_TYPE_COUNT];
if (isFilesTable) {
String deleteparam = uri.getQueryParameter(MediaStore.PARAM_DELETE_DATA);
if (deleteparam == null || ! deleteparam.equals("false")) {
@@ -4723,7 +4724,13 @@
mCallingIdentity.get().setOwned(id, false);
deleteIfAllowed(uri, extras, data);
- count += qb.delete(helper, BaseColumns._ID + "=" + id, null);
+ int res = qb.delete(helper, BaseColumns._ID + "=" + id, null);
+ count += res;
+ // Avoid ArrayIndexOutOfBounds if more mediaTypes are added,
+ // but mediaTypeSize is not updated
+ if (res > 0 && mediaType < countPerMediaType.length) {
+ countPerMediaType[mediaType] += res;
+ }
// Only need to inform DownloadProvider about the downloads deleted on
// external volume.
@@ -4781,7 +4788,7 @@
if (isFilesTable && !isCallingPackageSelf()) {
Metrics.logDeletion(volumeName, mCallingIdentity.get().uid,
- getCallingPackageOrSelf(), count);
+ getCallingPackageOrSelf(), count, countPerMediaType);
}
}
diff --git a/src/com/android/providers/media/scan/ModernMediaScanner.java b/src/com/android/providers/media/scan/ModernMediaScanner.java
index 5dc59d4..27e3711 100644
--- a/src/com/android/providers/media/scan/ModernMediaScanner.java
+++ b/src/com/android/providers/media/scan/ModernMediaScanner.java
@@ -47,6 +47,8 @@
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import static com.android.providers.media.util.Metrics.translateReason;
+
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
@@ -511,12 +513,20 @@
queryArgs.putInt(MediaStore.QUERY_ARG_MATCH_TRASHED, MediaStore.MATCH_INCLUDE);
queryArgs.putInt(MediaStore.QUERY_ARG_MATCH_FAVORITE, MediaStore.MATCH_INCLUDE);
- try (Cursor c = mResolver.query(mFilesUri, new String[] { FileColumns._ID },
+ final int[] countPerMediaType = new int[FileColumns.MEDIA_TYPE_COUNT];
+ try (Cursor c = mResolver.query(mFilesUri,
+ new String[] { FileColumns._ID, FileColumns.MEDIA_TYPE },
queryArgs, mSignal)) {
while (c.moveToNext()) {
final long id = c.getLong(0);
if (Arrays.binarySearch(scannedIds, id) < 0) {
mUnknownIds.add(id);
+ final int mediaType = c.getInt(1);
+ // Avoid ArrayIndexOutOfBounds if more mediaTypes are added,
+ // but mediaTypeSize is not updated
+ if (mediaType < countPerMediaType.length) {
+ countPerMediaType[mediaType]++;
+ }
}
}
} finally {
@@ -538,6 +548,10 @@
}
applyPending();
} finally {
+ if (mUnknownIds.size() > 0) {
+ String scanReason = "scan triggered by reason: " + translateReason(mReason);
+ Metrics.logDeletionPersistent(mVolumeName, scanReason, countPerMediaType);
+ }
Trace.endSection();
}
}
diff --git a/src/com/android/providers/media/util/Metrics.java b/src/com/android/providers/media/util/Metrics.java
index 86a0302..410da3a 100644
--- a/src/com/android/providers/media/util/Metrics.java
+++ b/src/com/android/providers/media/util/Metrics.java
@@ -60,12 +60,30 @@
normalizedInsertCount, normalizedUpdateCount, normalizedDeleteCount);
}
- public static void logDeletion(@NonNull String volumeName, int uid, String packageName,
- int itemCount) {
- Logging.logPersistent(String.format(
- "Deleted %3$d items on %1$s due to %2$s",
- volumeName, packageName, itemCount));
+ /**
+ * Logs persistent deletion logs on-device.
+ */
+ public static void logDeletionPersistent(@NonNull String volumeName, String reason,
+ int[] countPerMediaType) {
+ final StringBuilder builder = new StringBuilder("Deleted ");
+ for (int count: countPerMediaType) {
+ builder.append(count).append(' ');
+ }
+ builder.append("items on ")
+ .append(volumeName)
+ .append(" due to ")
+ .append(reason);
+ Logging.logPersistent(builder.toString());
+ }
+
+ /**
+ * Logs persistent deletion logs on-device and stats metrics. Count of items per-media-type
+ * are not uploaded to MediaProviderStats logs.
+ */
+ public static void logDeletion(@NonNull String volumeName, int uid, String packageName,
+ int itemCount, int[] countPerMediaType) {
+ logDeletionPersistent(volumeName, packageName, countPerMediaType);
MediaProviderStatsLog.write(MEDIA_CONTENT_DELETED,
translateVolumeName(volumeName), uid, itemCount);
}
diff --git a/tests/src/com/android/providers/media/util/MetricsTest.java b/tests/src/com/android/providers/media/util/MetricsTest.java
index 41e25b5..688e2e9 100644
--- a/tests/src/com/android/providers/media/util/MetricsTest.java
+++ b/tests/src/com/android/providers/media/util/MetricsTest.java
@@ -41,7 +41,8 @@
final String packageName = "com.example";
Metrics.logScan(volumeName, MediaScanner.REASON_UNKNOWN, 42, 42, 42, 42, 42);
- Metrics.logDeletion(volumeName, 42, packageName, 42);
+ Metrics.logDeletionPersistent(volumeName, "scanReason", new int[] { 42 });
+ Metrics.logDeletion(volumeName, 42, packageName, 42, new int[] { 42 });
Metrics.logPermissionGranted(volumeName, 42, packageName, 42);
Metrics.logPermissionDenied(volumeName, 42, packageName, 42);
Metrics.logSchemaChange(volumeName, 42, 42, 42, 42);