Add statistics logging for MediaProvider.
As part of becoming a Mainline module, we need to understand basic
information about the health of our module in the wild. For the
MediaProvider module, we're interested in identifying these cases:
-- When scan operations result in an unexpectedly large number of
inserts, updates, or deletes in proportion to the total number of
files indexed. This typically indicates user data loss or a missing
database upgrade step.
-- When the overall duration of scan operations becomes significantly
slower in relation to the number of files indexed. This typically
indicates an indexing performance regression.
-- When a scan operation skips over an entire directory tree. This
can indicate an app placing ".nomedia" files in unexpected locations.
-- When a large number of media files are deleted by a specific
app. This can help identify data loss bugs caused by MediaProvider
directly, or attribute data loss bugs in other apps.
-- When database upgrade/downgrade operations take a substantial
amount of time in proportion to the total number of files. This
typically indicates a performance regression.
-- When performing idle maintenance, a large number of stale or
expiring media can indicate an invalidation bug.
Bug: 143723019
Test: manual
Change-Id: I89c5b5b51a843a67348a7bb4b8e6ac01fb2b15b9
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 1fd3abf..e8c0e15 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -1275,7 +1275,7 @@
// Permission check not necessary as it's meant for applications to write to
// statsd.
android::util::stats_write(util::APP_BREADCRUMB_REPORTED,
- IPCThreadState::self()->getCallingUid(), label,
+ (int32_t) IPCThreadState::self()->getCallingUid(), label,
state);
return Status::ok();
}
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index b9051da..bae912d 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -50,6 +50,7 @@
import "frameworks/base/core/proto/android/stats/launcher/launcher.proto";
import "frameworks/base/core/proto/android/stats/location/location_enums.proto";
import "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.proto";
+import "frameworks/base/core/proto/android/stats/mediaprovider/mediaprovider_enums.proto";
import "frameworks/base/core/proto/android/stats/storage/storage_enums.proto";
import "frameworks/base/core/proto/android/stats/style/style_enums.proto";
import "frameworks/base/core/proto/android/telecomm/enums.proto";
@@ -342,6 +343,16 @@
VmsClientConnectionStateChanged vms_client_connection_state_changed = 230;
GpsLocationStatusReported gps_location_status_reported = 231;
GpsTimeToFirstFixReported gps_time_to_first_fix_reported = 232;
+ MediaProviderScanEvent media_provider_scan_event =
+ 233 [(log_from_module) = "mediaprovider"];
+ MediaProviderDeletionEvent media_provider_deletion_event =
+ 234 [(log_from_module) = "mediaprovider"];
+ MediaProviderPermissionEvent media_provider_permission_event =
+ 235 [(log_from_module) = "mediaprovider"];
+ MediaProviderSchemaChange media_provider_schema_change =
+ 236 [(log_from_module) = "mediaprovider"];
+ MediaProviderIdleMaintenance media_provider_idle_maintenance =
+ 237 [(log_from_module) = "mediaprovider"];
}
// Pulled events will start at field 10000.
@@ -3799,6 +3810,124 @@
optional State state = 2;
}
+/**
+ * Logs when MediaProvider has successfully finished scanning a storage volume.
+ *
+ * Logged from:
+ * packages/providers/MediaProvider/src/com/android/providers/media/scan/ModernMediaScanner.java
+ */
+message MediaProviderScanEvent {
+ enum Reason {
+ // Scan triggered due to unknown reason
+ UNKNOWN = 0;
+ // Scan triggered due to storage volume being mounted
+ MOUNTED = 1;
+ // Scan triggered due to explicit user action or app request
+ DEMAND = 2;
+ // Scan triggered due to idle maintenance
+ IDLE = 3;
+ }
+
+ // Volume type that this event pertains to
+ optional android.stats.mediaprovider.VolumeType volume_type = 1;
+ // Reason why this scan was triggered
+ optional Reason reason = 2;
+ // Total number of files scanned
+ optional int64 item_count = 3;
+ // Duration of scan, normalized per file
+ optional float normalized_duration_millis = 4;
+ // Number of database inserts, normalized per file
+ optional float normalized_insert_count = 5;
+ // Number of database updates, normalized per file
+ optional float normalized_update_count = 6;
+ // Number of database deletes, normalized per file
+ optional float normalized_delete_count = 7;
+}
+
+/**
+ * Logs when an app has asked MediaProvider to delete media belonging to the user.
+ *
+ * Logged from:
+ * packages/providers/MediaProvider/src/com/android/providers/media/MediaProvider.java
+ */
+message MediaProviderDeletionEvent {
+ // Volume type that this event pertains to
+ optional android.stats.mediaprovider.VolumeType volume_type = 1;
+ // Device timestamp when this deletion event occurred
+ optional int64 timestamp_millis = 2;
+ // App that requested deletion
+ optional string package_name = 3;
+ // Number of items that were deleted
+ optional int32 item_count = 4;
+}
+
+/**
+ * Logs when an app has asked MediaProvider to grant them access to media belonging to the user.
+ *
+ * Logged from:
+ * packages/providers/MediaProvider/src/com/android/providers/media/PermissionActivity.java
+ */
+message MediaProviderPermissionEvent {
+ enum Result {
+ UNKNOWN = 0;
+ USER_GRANTED = 1;
+ AUTO_GRANTED = 2;
+ USER_DENIED = 3;
+ USER_DENIED_WITH_PREJUDICE = 4;
+ AUTO_DENIED = 5;
+ }
+
+ // Volume type that this event pertains to
+ optional android.stats.mediaprovider.VolumeType volume_type = 1;
+ // Device timestamp when this permission event occurred
+ optional int64 timestamp_millis = 2;
+ // App that requested permission
+ optional string package_name = 3;
+ // Number of items that were requested
+ optional int32 item_count = 4;
+ // Result of this request
+ optional Result result = 5;
+}
+
+/**
+ * Logs when MediaProvider has finished upgrading or downgrading its database schema.
+ *
+ * Logged from:
+ * packages/providers/MediaProvider/src/com/android/providers/media/DatabaseHelper.java
+ */
+message MediaProviderSchemaChange {
+ // Volume type that this event pertains to
+ optional android.stats.mediaprovider.VolumeType volume_type = 1;
+ // Old database version code
+ optional int32 version_from = 2;
+ // New database version code
+ optional int32 version_to = 3;
+ // Total number of files in database
+ optional int64 item_count = 4;
+ // Duration of schema change, normalized per file
+ optional float normalized_duration_millis = 5;
+}
+
+/**
+ * Logs when MediaProvider has finished an idle maintenance job.
+ *
+ * Logged from:
+ * packages/providers/MediaProvider/src/com/android/providers/media/MediaProvider.java
+ */
+message MediaProviderIdleMaintenance {
+ // Volume type that this event pertains to
+ optional android.stats.mediaprovider.VolumeType volume_type = 1;
+
+ // Total number of files in database
+ optional int64 item_count = 2;
+ // Duration of idle maintenance, normalized per file
+ optional float normalized_duration_millis = 3;
+ // Number of thumbnails found to be stale, normalized per file
+ optional float normalized_stale_thumbnails = 4;
+ // Number of items found to be expired, normalized per file
+ optional float normalized_expired_media = 5;
+}
+
//////////////////////////////////////////////////////////////////////
// Pulled atoms below this line //
//////////////////////////////////////////////////////////////////////
diff --git a/core/proto/android/stats/mediaprovider/mediaprovider_enums.proto b/core/proto/android/stats/mediaprovider/mediaprovider_enums.proto
new file mode 100644
index 0000000..138782b
--- /dev/null
+++ b/core/proto/android/stats/mediaprovider/mediaprovider_enums.proto
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.stats.mediaprovider;
+option java_multiple_files = true;
+
+enum VolumeType {
+ // Volume is unknown
+ UNKNOWN = 0;
+ // Volume is MediaStore.VOLUME_INTERNAL
+ INTERNAL = 1;
+ // Volume is MediaStore.VOLUME_EXTERNAL_PRIMARY
+ EXTERNAL_PRIMARY = 2;
+ // Volume is non-primary external storage
+ EXTERNAL_OTHER = 3;
+}