summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Sergey Nikolaienkov <sergeynv@google.com> 2022-10-27 12:46:17 +0200
committer Sergey Nikolaienkov <sergeynv@google.com> 2022-10-29 11:21:15 +0200
commita6a1932afdd62b64d7f61a0caa25f31df641e357 (patch)
tree1b3155ef9349e40fa3cdb6db687f0b2d79e05d9c
parenta98e6c7cff4c6f50b9dc5dbe3014a302d751255e (diff)
Refresh MediaProvider's ATrace events
Add new ATrace events to PickerDataLayer, PickerSyncController and PickerDbFacade. Add prefixes to existing ATrace events on MediaProvider, MediaService, DatabaseUtils, ModernMediaScanner etc. Update trance.sh script to use Perfetto instead of de facto deprecated systrace tool (Perfetto is recommended for devices running Android 10 and higher). Add Perfetto tracing config file perfetto_config.pbtx. Bug: 253186784 Test: m and install MediaProvider APEX Test: ./trace.sh Change-Id: Ib043068378ac3f85bb55a765b57c4eed7e4a8f31
-rw-r--r--perfetto_config.pbtx87
-rw-r--r--src/com/android/providers/media/DatabaseHelper.java25
-rw-r--r--src/com/android/providers/media/MediaProvider.java40
-rw-r--r--src/com/android/providers/media/MediaService.java2
-rw-r--r--src/com/android/providers/media/photopicker/PickerDataLayer.java86
-rw-r--r--src/com/android/providers/media/photopicker/PickerSyncController.java287
-rw-r--r--src/com/android/providers/media/photopicker/data/PickerDbFacade.java10
-rw-r--r--src/com/android/providers/media/scan/ModernMediaScanner.java20
-rw-r--r--src/com/android/providers/media/util/DatabaseUtils.java5
-rw-r--r--src/com/android/providers/media/util/SpecialFormatDetector.java4
-rw-r--r--src/com/android/providers/media/util/XAttrUtils.java2
-rwxr-xr-xtrace.sh4
12 files changed, 392 insertions, 180 deletions
diff --git a/perfetto_config.pbtx b/perfetto_config.pbtx
new file mode 100644
index 000000000..ee6395d7d
--- /dev/null
+++ b/perfetto_config.pbtx
@@ -0,0 +1,87 @@
+buffers: {
+ size_kb: 63488
+ fill_policy: DISCARD
+}
+buffers: {
+ size_kb: 2048
+ fill_policy: DISCARD
+}
+
+data_sources: {
+ config {
+ name: "linux.ftrace"
+
+ # See: https://perfetto.dev/docs/data-sources/atrace#traceconfig
+ ftrace_config {
+ ftrace_events: "ftrace/print"
+
+ # Trace all ContentProvider commands and SQLite queries.
+ # See: https://source.corp.google.com/android-internal/frameworks/base/core/java/android/os/Trace.java?q=TRACE_TAG_DATABASE
+ # See: https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/database/sqlite/SQLiteConnection.java
+ # Uncomment to enable. Note: on a userdebug build it will add a trace for every SQLite
+ # command any application runs, which will make a trace very "noisy".
+ # atrace_categories: "database"
+
+ # Trace Binder IPC transactions.
+ # Uncomment to enable. Note: on a userdebug build it will add a trace for every Binder
+ # transaction for every application, which will make a trace very "noisy".
+ # atrace_categories: "binder_driver"
+
+ # ActivityManager, WindowManager, Graphics, View System.
+ # Uncomment to enable. Note: on a userdebug build it will traces form corresponding
+ # category for every application, which will make a trace very "noisy".
+ # atrace_categories: "wm"
+ # atrace_categories: "am"
+ # atrace_categories: "gfx"
+ # atrace_categories: "view"
+
+ # Trace MediaProviders' events.
+ atrace_apps: "com.android.providers.media.module"
+ atrace_apps: "com.google.android.providers.media.module"
+
+ # Trace Google Photos' events.
+ # Uncomment to enable.
+ # atrace_apps: "com.google.android.apps.photos"
+
+ # Trace all apps' events.
+ # Uncomment to enable.
+ # atrace_apps: "*"
+ }
+ }
+}
+
+# Android Logcat
+data_sources: {
+ config {
+ name: "android.log"
+ android_log_config {
+ min_prio: PRIO_VERBOSE # Default: PRIO_DEBUG
+
+ # If filter_tags non-empty ignores all log messages whose tag doesn't match one of the
+ # specified values.
+ # filter_tags: "MediaProvider"
+ # filter_tags: "PickerDataLayer"
+ # filter_tags: "PickerDbFacade"
+ # filter_tags: "PickerSyncController"
+
+ log_ids: LID_EVENTS
+ log_ids: LID_CRASH
+ log_ids: LID_KERNEL
+ log_ids: LID_DEFAULT
+ log_ids: LID_RADIO
+ log_ids: LID_SECURITY
+ log_ids: LID_STATS
+ log_ids: LID_SYSTEM
+ }
+ }
+}
+
+# This is for getting Thread<>Process associations and full process names.
+data_sources: {
+ config {
+ name: "linux.process_stats"
+ }
+}
+
+# Max duration: 1 min
+duration_ms: 60000
diff --git a/src/com/android/providers/media/DatabaseHelper.java b/src/com/android/providers/media/DatabaseHelper.java
index d2dd12a29..1a4b04f68 100644
--- a/src/com/android/providers/media/DatabaseHelper.java
+++ b/src/com/android/providers/media/DatabaseHelper.java
@@ -370,7 +370,7 @@ public class DatabaseHelper extends SQLiteOpenHelper implements AutoCloseable {
.setIsPending(isPending)
.setPath(path)
.build();
- Trace.beginSection("_INSERT");
+ Trace.beginSection(traceSectionName("_INSERT"));
try {
mFilesListener.onInsert(DatabaseHelper.this, insertedRow);
} finally {
@@ -424,7 +424,7 @@ public class DatabaseHelper extends SQLiteOpenHelper implements AutoCloseable {
.setOwnerPackageName(newOwnerPackage)
.build();
- Trace.beginSection("_UPDATE");
+ Trace.beginSection(traceSectionName("_UPDATE"));
try {
mFilesListener.onUpdate(DatabaseHelper.this, oldRow, newRow);
} finally {
@@ -451,7 +451,7 @@ public class DatabaseHelper extends SQLiteOpenHelper implements AutoCloseable {
.setOwnerPackageName(ownerPackage)
.setPath(path)
.build();
- Trace.beginSection("_DELETE");
+ Trace.beginSection(traceSectionName("_DELETE"));
try {
mFilesListener.onDelete(DatabaseHelper.this, deletedRow);
} finally {
@@ -462,7 +462,7 @@ public class DatabaseHelper extends SQLiteOpenHelper implements AutoCloseable {
});
db.setCustomScalarFunction("_GET_ID", (arg) -> {
if (mIdGenerator != null && !mSchemaLock.isWriteLockedByCurrentThread()) {
- Trace.beginSection("_GET_ID");
+ Trace.beginSection(traceSectionName("_GET_ID"));
try {
return mIdGenerator.apply(arg);
} finally {
@@ -696,11 +696,13 @@ public class DatabaseHelper extends SQLiteOpenHelper implements AutoCloseable {
}
public void beginTransaction() {
- Trace.beginSection("transaction " + getDatabaseName());
- Trace.beginSection("beginTransaction");
+ Trace.beginSection(traceSectionName("transaction"));
+ Trace.beginSection(traceSectionName("beginTransaction"));
try {
beginTransactionInternal();
} finally {
+ // Only end the "beginTransaction" section. We'll end the "transaction" section in
+ // endTransaction().
Trace.endSection();
}
}
@@ -729,11 +731,12 @@ public class DatabaseHelper extends SQLiteOpenHelper implements AutoCloseable {
}
public void endTransaction() {
- Trace.beginSection("endTransaction");
+ Trace.beginSection(traceSectionName("endTransaction"));
try {
endTransactionInternal();
} finally {
Trace.endSection();
+ // End "transaction" section, which we started in beginTransaction().
Trace.endSection();
}
}
@@ -860,7 +863,7 @@ public class DatabaseHelper extends SQLiteOpenHelper implements AutoCloseable {
}
private void notifySingleChangeInternal(@NonNull Uri uri, int flags) {
- Trace.beginSection("notifySingleChange");
+ Trace.beginSection(traceSectionName("notifySingleChange"));
try {
mContext.getContentResolver().notifyChange(uri, null, flags);
} finally {
@@ -869,7 +872,7 @@ public class DatabaseHelper extends SQLiteOpenHelper implements AutoCloseable {
}
private void notifyChangeInternal(@NonNull Collection<Uri> uris, int flags) {
- Trace.beginSection("notifyChange");
+ Trace.beginSection(traceSectionName("notifyChange"));
try {
for (List<Uri> partition : Iterables.partition(uris, NOTIFY_BATCH_SIZE)) {
mContext.getContentResolver().notifyChange(partition, null, flags);
@@ -2398,4 +2401,8 @@ public class DatabaseHelper extends SQLiteOpenHelper implements AutoCloseable {
boolean isDatabaseRecovering() {
return mIsRecovering.get();
}
+
+ private String traceSectionName(@NonNull String method) {
+ return "DH[" + getDatabaseName() + "]." + method;
+ }
}
diff --git a/src/com/android/providers/media/MediaProvider.java b/src/com/android/providers/media/MediaProvider.java
index 6684f4741..7967399f4 100644
--- a/src/com/android/providers/media/MediaProvider.java
+++ b/src/com/android/providers/media/MediaProvider.java
@@ -688,7 +688,7 @@ public class MediaProvider extends ContentProvider {
}
private final void updateQuotaTypeForUri(@NonNull Uri uri, int mediaType) {
- Trace.beginSection("updateQuotaTypeForUri");
+ Trace.beginSection("MP.updateQuotaTypeForUri");
File file;
try {
file = queryForDataFile(uri, null);
@@ -824,7 +824,7 @@ public class MediaProvider extends ContentProvider {
helper.postBackground(() -> {
// Item no longer exists, so revoke all access to it
- Trace.beginSection("revokeUriPermission");
+ Trace.beginSection("MP.revokeUriPermission");
try {
acceptWithExpansion((uri) -> {
getContext().revokeUriPermission(uri, ~0);
@@ -3372,7 +3372,7 @@ public class MediaProvider extends ContentProvider {
private Cursor query(Uri uri, String[] projection, Bundle queryArgs,
CancellationSignal signal, boolean forSelf) {
- Trace.beginSection("query");
+ Trace.beginSection("MP.query [" + uri + ']');
try {
return queryInternal(uri, projection, queryArgs, signal, forSelf);
} catch (FallbackException e) {
@@ -3733,7 +3733,7 @@ public class MediaProvider extends ContentProvider {
private void ensureFileColumns(int match, @NonNull Uri uri, @NonNull Bundle extras,
@NonNull ContentValues values, boolean makeUnique, @Nullable String currentPath)
throws VolumeArgumentException, VolumeNotFoundException {
- Trace.beginSection("ensureFileColumns");
+ Trace.beginSection("MP.ensureFileColumns");
Objects.requireNonNull(uri);
Objects.requireNonNull(extras);
@@ -4272,7 +4272,7 @@ public class MediaProvider extends ContentProvider {
}
private int bulkInsertPlaylist(@NonNull Uri uri, @NonNull ContentValues[] values) {
- Trace.beginSection("bulkInsertPlaylist");
+ Trace.beginSection("MP.bulkInsertPlaylist");
try {
try {
return addPlaylistMembers(uri, values);
@@ -4783,7 +4783,7 @@ public class MediaProvider extends ContentProvider {
@Override
public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues values,
@Nullable Bundle extras) {
- Trace.beginSection("insert");
+ Trace.beginSection("MP.insert [" + uri + ']');
try {
try {
return insertInternal(uri, values, extras);
@@ -5256,7 +5256,7 @@ public class MediaProvider extends ContentProvider {
*/
private @NonNull SQLiteQueryBuilder getQueryBuilder(int type, int match,
@NonNull Uri uri, @NonNull Bundle extras, @Nullable Consumer<String> honored) {
- Trace.beginSection("getQueryBuilder");
+ Trace.beginSection("MP.getQueryBuilder");
try {
return getQueryBuilderInternal(type, match, uri, extras, honored);
} finally {
@@ -5898,7 +5898,7 @@ public class MediaProvider extends ContentProvider {
@Override
public int delete(@NonNull Uri uri, @Nullable Bundle extras) {
- Trace.beginSection("delete");
+ Trace.beginSection("MP.delete [" + uri + ']');
try {
return deleteInternal(uri, extras);
} catch (FallbackException e) {
@@ -6243,7 +6243,7 @@ public class MediaProvider extends ContentProvider {
@Override
public Bundle call(String method, String arg, Bundle extras) {
- Trace.beginSection("call");
+ Trace.beginSection("MP.call [" + method + ']');
try {
return callInternal(method, arg, extras);
} finally {
@@ -6941,7 +6941,7 @@ public class MediaProvider extends ContentProvider {
}
private void invalidateThumbnails(Uri uri) {
- Trace.beginSection("invalidateThumbnails");
+ Trace.beginSection("MP.invalidateThumbnails");
try {
invalidateThumbnailsInternal(uri);
} finally {
@@ -6997,7 +6997,7 @@ public class MediaProvider extends ContentProvider {
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values,
@Nullable Bundle extras) {
- Trace.beginSection("update");
+ Trace.beginSection("MP.update [" + uri + ']');
try {
return updateInternal(uri, values, extras);
} catch (FallbackException e) {
@@ -7170,7 +7170,7 @@ public class MediaProvider extends ContentProvider {
}
if (!isCallingPackageSelf()) {
- Trace.beginSection("filter");
+ Trace.beginSection("MP.filter");
// We default to filtering mutable columns, except when we know
// the single item being updated is pending; when it's finally
@@ -7275,7 +7275,7 @@ public class MediaProvider extends ContentProvider {
&& !initialValues.containsKey(MediaColumns.DATA)
&& !isThumbnail
&& allowMovement) {
- Trace.beginSection("movement");
+ Trace.beginSection("MP.movement");
// We only support movement under well-defined collections
switch (match) {
@@ -7401,7 +7401,7 @@ public class MediaProvider extends ContentProvider {
// it's applied, we need to snapshot affected IDs here
final LongArray updatedIds = new LongArray();
if (triggerInvalidate || triggerScan) {
- Trace.beginSection("snapshot");
+ Trace.beginSection("MP.snapshot");
final LocalCallingIdentity token = clearLocalCallingIdentity();
try (Cursor c = qb.query(helper, new String[] { FileColumns._ID },
userWhere, userWhereArgs, null, null, null, null, null)) {
@@ -7468,7 +7468,7 @@ public class MediaProvider extends ContentProvider {
// If the caller tried (and failed) to update metadata, the file on disk
// might have changed, to scan it to collect the latest metadata.
if (triggerInvalidate || triggerScan) {
- Trace.beginSection("invalidate");
+ Trace.beginSection("MP.invalidate");
final LocalCallingIdentity token = clearLocalCallingIdentity();
try {
for (int i = 0; i < updatedIds.size(); i++) {
@@ -7641,7 +7641,7 @@ public class MediaProvider extends ContentProvider {
* that the playlist entry is retained to avoid user data loss.
*/
private void resolvePlaylistMembers(@NonNull Uri playlistUri) {
- Trace.beginSection("resolvePlaylistMembers");
+ Trace.beginSection("MP.resolvePlaylistMembers");
try {
final DatabaseHelper helper;
try {
@@ -8103,7 +8103,7 @@ public class MediaProvider extends ContentProvider {
final boolean allowHidden = isCallingPackageAllowedHidden();
final int match = matchUri(uri, allowHidden);
- Trace.beginSection("ensureThumbnail");
+ Trace.beginSection("MP.ensureThumbnail");
final LocalCallingIdentity token = clearLocalCallingIdentity();
try {
switch (match) {
@@ -8969,7 +8969,7 @@ public class MediaProvider extends ContentProvider {
final LongArray res = new LongArray();
final LongArray freeOffsets = new LongArray();
- Trace.beginSection("getRedactionRanges");
+ Trace.beginSection("MP.getRedactionRanges");
try {
if (ExifInterface.isSupportedMimeType(mimeType)) {
final ExifInterface exif = new ExifInterface(fis.getFD());
@@ -9019,7 +9019,7 @@ public class MediaProvider extends ContentProvider {
private FileAccessAttributes queryForFileAttributes(final String path)
throws FileNotFoundException {
- Trace.beginSection("queryFileAttr");
+ Trace.beginSection("MP.queryFileAttr");
final Uri contentUri = FileUtils.getContentUriForPath(path);
final String[] projection = new String[]{
MediaColumns._ID,
@@ -9950,7 +9950,7 @@ public class MediaProvider extends ContentProvider {
*/
private void enforceCallingPermission(@NonNull Uri uri, @NonNull Bundle extras,
boolean forWrite) {
- Trace.beginSection("enforceCallingPermission");
+ Trace.beginSection("MP.enforceCallingPermission");
try {
enforceCallingPermissionInternal(uri, extras, forWrite);
} finally {
diff --git a/src/com/android/providers/media/MediaService.java b/src/com/android/providers/media/MediaService.java
index c376bc3fd..690114d67 100644
--- a/src/com/android/providers/media/MediaService.java
+++ b/src/com/android/providers/media/MediaService.java
@@ -64,7 +64,7 @@ public class MediaService extends JobIntentService {
@Override
protected void onHandleWork(Intent intent) {
- Trace.beginSection(intent.getAction());
+ Trace.beginSection("MediaService.handle[" + intent.getAction() + ']');
if (Log.isLoggable(TAG, Log.INFO)) {
Log.i(TAG, "Begin " + intent);
}
diff --git a/src/com/android/providers/media/photopicker/PickerDataLayer.java b/src/com/android/providers/media/photopicker/PickerDataLayer.java
index 217a79913..ea4067a5e 100644
--- a/src/com/android/providers/media/photopicker/PickerDataLayer.java
+++ b/src/com/android/providers/media/photopicker/PickerDataLayer.java
@@ -17,6 +17,8 @@
package com.android.providers.media.photopicker;
import static android.provider.CloudMediaProviderContract.METHOD_GET_MEDIA_COLLECTION_INFO;
+import static android.provider.CloudMediaProviderContract.MediaCollectionInfo.ACCOUNT_CONFIGURATION_INTENT;
+import static android.provider.CloudMediaProviderContract.MediaCollectionInfo.ACCOUNT_NAME;
import static com.android.providers.media.PickerUriResolver.getAlbumUri;
import static com.android.providers.media.PickerUriResolver.getMediaCollectionInfoUri;
@@ -26,11 +28,14 @@ import android.content.Intent;
import android.database.Cursor;
import android.database.MergeCursor;
import android.os.Bundle;
-import android.provider.CloudMediaProviderContract;
+import android.os.Trace;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import com.android.providers.media.photopicker.data.CloudProviderQueryExtras;
import com.android.providers.media.photopicker.data.PickerDbFacade;
@@ -59,8 +64,18 @@ public class PickerDataLayer {
public Cursor fetchMedia(Bundle queryArgs) {
final CloudProviderQueryExtras queryExtras
= CloudProviderQueryExtras.fromMediaStoreBundle(queryArgs, mLocalProvider);
- final String albumId = queryExtras.getAlbumId();
final String authority = queryExtras.getAlbumAuthority();
+
+ Trace.beginSection(traceSectionName("fetchMedia", authority));
+ try {
+ return fetchMediaInternal(authority, queryExtras);
+ } finally {
+ Trace.endSection();
+ }
+ }
+
+ private Cursor fetchMediaInternal(String authority, CloudProviderQueryExtras queryExtras) {
+ final String albumId = queryExtras.getAlbumId();
// Use media table for all media except albums. Merged categories like,
// favorites and video are tagged in the media table and are not a part of
// album_media.
@@ -99,6 +114,15 @@ public class PickerDataLayer {
}
public Cursor fetchAlbums(Bundle queryArgs) {
+ Trace.beginSection(traceSectionName("fetchAlbums"));
+ try {
+ return fetchAlbumsInternal(queryArgs);
+ } finally {
+ Trace.endSection();
+ }
+ }
+
+ private Cursor fetchAlbumsInternal(Bundle queryArgs) {
// Refresh the 'media' table so that 'merged' albums (Favorites and Videos) are up to date
mSyncController.syncAllMedia();
@@ -136,37 +160,54 @@ public class PickerDataLayer {
return mergeCursor;
}
+ @Nullable
public AccountInfo fetchCloudAccountInfo() {
final String cloudProvider = mDbFacade.getCloudProvider();
if (cloudProvider == null) {
return null;
}
+ Trace.beginSection(traceSectionName("fetchCloudAccountInfo"));
try {
- final Bundle accountBundle = mContext.getContentResolver().call(
- getMediaCollectionInfoUri(cloudProvider), METHOD_GET_MEDIA_COLLECTION_INFO,
- /* arg */ null, /* extras */ null);
- final String accountName = accountBundle.getString(
- CloudMediaProviderContract.MediaCollectionInfo.ACCOUNT_NAME);
- final Intent configIntent = (Intent) accountBundle.getParcelable(
- CloudMediaProviderContract.MediaCollectionInfo.ACCOUNT_CONFIGURATION_INTENT);
-
- if (accountName == null) {
- return null;
- }
-
- return new AccountInfo(accountName, configIntent);
+ return fetchCloudAccountInfoInternal(cloudProvider);
} catch (Exception e) {
Log.w(TAG, "Failed to fetch account info from cloud provider: " + cloudProvider, e);
return null;
+ } finally {
+ Trace.endSection();
+ }
+ }
+
+ @Nullable
+ public AccountInfo fetchCloudAccountInfoInternal(@NonNull String cloudProvider) {
+ final Bundle accountBundle = mContext.getContentResolver()
+ .call(getMediaCollectionInfoUri(cloudProvider), METHOD_GET_MEDIA_COLLECTION_INFO,
+ /* arg */ null, /* extras */ null);
+
+ final String accountName = accountBundle.getString(ACCOUNT_NAME);
+ if (accountName == null) {
+ return null;
}
+ final Intent configIntent = accountBundle.getParcelable(ACCOUNT_CONFIGURATION_INTENT);
+
+ return new AccountInfo(accountName, configIntent);
}
- private Cursor queryProviderAlbums(String authority, Bundle queryArgs) {
+ private Cursor queryProviderAlbums(@Nullable String authority, Bundle queryArgs) {
if (authority == null) {
// Can happen if there is no cloud provider
return null;
}
+
+ Trace.beginSection(traceSectionName("queryProviderAlbums", authority));
+ try {
+ return queryProviderAlbumsInternal(authority, queryArgs);
+ } finally {
+ Trace.endSection();
+ }
+ }
+
+ private Cursor queryProviderAlbumsInternal(@NonNull String authority, Bundle queryArgs) {
try {
return mContext.getContentResolver().query(getAlbumUri(authority),
/* projection */ null, queryArgs, /* cancellationSignal */ null);
@@ -180,6 +221,19 @@ public class PickerDataLayer {
return mLocalProvider.equals(authority);
}
+ private String traceSectionName(@NonNull String method) {
+ return traceSectionName(method, null);
+ }
+
+ private String traceSectionName(@NonNull String method, @Nullable String authority) {
+ final StringBuilder sb = new StringBuilder("PDL.")
+ .append(method);
+ if (authority != null) {
+ sb.append('[').append(isLocal(authority) ? "local" : "cloud").append(']');
+ }
+ return sb.toString();
+ }
+
public static class AccountInfo {
public final String accountName;
public final Intent accountConfigurationIntent;
diff --git a/src/com/android/providers/media/photopicker/PickerSyncController.java b/src/com/android/providers/media/photopicker/PickerSyncController.java
index 184e8fd48..3d0cf14b9 100644
--- a/src/com/android/providers/media/photopicker/PickerSyncController.java
+++ b/src/com/android/providers/media/photopicker/PickerSyncController.java
@@ -21,7 +21,8 @@ import static android.provider.CloudMediaProviderContract.EXTRA_ALBUM_ID;
import static android.provider.CloudMediaProviderContract.EXTRA_MEDIA_COLLECTION_ID;
import static android.provider.CloudMediaProviderContract.EXTRA_PAGE_TOKEN;
import static android.provider.CloudMediaProviderContract.EXTRA_SYNC_GENERATION;
-import static android.provider.CloudMediaProviderContract.MediaCollectionInfo;
+import static android.provider.CloudMediaProviderContract.MediaCollectionInfo.LAST_MEDIA_SYNC_GENERATION;
+import static android.provider.CloudMediaProviderContract.MediaCollectionInfo.MEDIA_COLLECTION_ID;
import static com.android.providers.media.PickerUriResolver.getDeletedMediaUri;
import static com.android.providers.media.PickerUriResolver.getMediaCollectionInfoUri;
@@ -37,6 +38,7 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Process;
+import android.os.Trace;
import android.os.storage.StorageManager;
import android.provider.CloudMediaProvider;
import android.provider.CloudMediaProviderContract;
@@ -94,7 +96,7 @@ public class PickerSyncController {
private static final int SYNC_TYPE_MEDIA_RESET = 3;
@IntDef(flag = false, prefix = { "SYNC_TYPE_" }, value = {
- SYNC_TYPE_NONE,
+ SYNC_TYPE_NONE,
SYNC_TYPE_MEDIA_INCREMENTAL,
SYNC_TYPE_MEDIA_FULL,
SYNC_TYPE_MEDIA_RESET,
@@ -160,18 +162,24 @@ public class PickerSyncController {
* Syncs the local and currently enabled cloud {@link CloudMediaProvider} instances
*/
public void syncAllMedia() {
- syncAllMediaFromProvider(mLocalProvider, /* retryOnFailure */ true);
-
- synchronized (mLock) {
- final String cloudProvider = mCloudProviderInfo.authority;
+ Trace.beginSection(traceSectionName("syncAllMedia"));
+ try {
+ syncAllMediaFromProvider(mLocalProvider, /* isLocal */ true, /* retryOnFailure */ true);
- syncAllMediaFromProvider(cloudProvider, /* retryOnFailure */ true);
+ synchronized (mLock) {
+ final String cloudProvider = mCloudProviderInfo.authority;
+ syncAllMediaFromProvider(cloudProvider, /* isLocal */ false,
+ /* retryOnFailure */ true);
- // Reset the album_media table every time we sync all media
- resetAlbumMedia();
+ // Reset the album_media table every time we sync all media
+ // TODO(sergeynv@): do we really need to reset for both providers?
+ resetAlbumMedia();
- // Set the latest cloud provider on the facade
- mDbFacade.setCloudProvider(cloudProvider);
+ // Set the latest cloud provider on the facade
+ mDbFacade.setCloudProvider(cloudProvider);
+ }
+ } finally {
+ Trace.endSection();
}
}
@@ -181,26 +189,27 @@ public class PickerSyncController {
*/
public void syncAlbumMedia(String albumId, boolean isLocal) {
if (isLocal) {
- syncAlbumMediaFromProvider(mLocalProvider, albumId);
+ syncAlbumMediaFromProvider(mLocalProvider, /* isLocal */ true, albumId);
} else {
synchronized (mLock) {
- syncAlbumMediaFromProvider(mCloudProviderInfo.authority, albumId);
+ syncAlbumMediaFromProvider(
+ mCloudProviderInfo.authority, /* isLocal */ false, albumId);
}
}
}
private void resetAlbumMedia() {
- executeSyncAlbumReset(mLocalProvider, /* albumId */ null);
+ executeSyncAlbumReset(mLocalProvider, /* isLocal */ true, /* albumId */ null);
synchronized (mLock) {
final String cloudProvider = mCloudProviderInfo.authority;
- executeSyncAlbumReset(cloudProvider, /* albumId */ null);
+ executeSyncAlbumReset(cloudProvider, /* isLocal */ false, /* albumId */ null);
}
}
- private void resetAllMedia(String authority) {
- executeSyncReset(authority);
- resetCachedMediaCollectionInfo(authority);
+ private void resetAllMedia(String authority, boolean isLocal) {
+ executeSyncReset(authority, isLocal);
+ resetCachedMediaCollectionInfo(authority, isLocal);
}
@NonNull
@@ -242,7 +251,12 @@ public class PickerSyncController {
* otherwise
*/
public boolean setCloudProvider(String authority) {
- return setCloudProviderInternal(authority, /* ignoreAllowlist */ false);
+ Trace.beginSection(traceSectionName("setCloudProvider"));
+ try {
+ return setCloudProviderInternal(authority, /* ignoreAllowlist */ false);
+ } finally {
+ Trace.endSection();
+ }
}
/**
@@ -250,7 +264,12 @@ public class PickerSyncController {
*/
@VisibleForTesting
public void forceSetCloudProvider(String authority) {
- setCloudProviderInternal(authority, /* ignoreAllowlist */ true);
+ Trace.beginSection(traceSectionName("forceSetCloudProvider"));
+ try {
+ setCloudProviderInternal(authority, /* ignoreAllowlist */ true);
+ } finally {
+ Trace.endSection();
+ }
}
private boolean setCloudProviderInternal(String authority, boolean ignoreAllowList) {
@@ -266,7 +285,7 @@ public class PickerSyncController {
synchronized (mLock) {
final String oldAuthority = mCloudProviderInfo.authority;
persistCloudProviderInfo(newProviderInfo);
- resetCachedMediaCollectionInfo(newProviderInfo.authority);
+ resetCachedMediaCollectionInfo(newProviderInfo.authority, /* isLocal */ false);
// Disable cloud provider queries on the db until next sync
// This will temporarily *clear* the cloud provider on the db facade and prevent
@@ -435,55 +454,60 @@ public class PickerSyncController {
editor.apply();
}
- private void syncAlbumMediaFromProvider(String authority, String albumId) {
+ private void syncAlbumMediaFromProvider(String authority, boolean isLocal, String albumId) {
final Bundle queryArgs = new Bundle();
queryArgs.putString(EXTRA_ALBUM_ID, albumId);
+ Trace.beginSection(traceSectionName("syncAlbumMediaFromProvider", isLocal));
try {
- executeSyncAlbumReset(authority, albumId);
+ executeSyncAlbumReset(authority, isLocal, albumId);
if (authority != null) {
- executeSyncAddAlbum(authority, albumId, queryArgs);
+ executeSyncAddAlbum(authority, isLocal, albumId, queryArgs);
}
} catch (RuntimeException e) {
// Unlike syncAllMediaFromProvider, we don't retry here because any errors would have
// occurred in fetching all the album_media since incremental sync is not supported.
// A full sync is therefore unlikely to resolve any issue
Log.e(TAG, "Failed to sync album media", e);
+ } finally {
+ Trace.endSection();
}
}
- private void syncAllMediaFromProvider(String authority, boolean retryOnFailure) {
+ private void syncAllMediaFromProvider(String authority, boolean isLocal,
+ boolean retryOnFailure) {
+ Trace.beginSection(traceSectionName("syncAllMediaFromProvider", isLocal));
try {
- final SyncRequestParams params = getSyncRequestParams(authority);
+ final SyncRequestParams params = getSyncRequestParams(authority, isLocal);
switch (params.syncType) {
case SYNC_TYPE_MEDIA_RESET:
// Can only happen when |authority| has been set to null and we need to clean up
- resetAllMedia(authority);
+ resetAllMedia(authority, isLocal);
break;
case SYNC_TYPE_MEDIA_FULL:
- resetAllMedia(authority);
+ resetAllMedia(authority, isLocal);
// Pass a mutable empty bundle intentionally because it might be populated with
// the next page token as part of a query to a cloud provider supporting
// pagination
- executeSyncAdd(authority, params.getMediaCollectionId(),
+ executeSyncAdd(authority, isLocal, params.getMediaCollectionId(),
/* isIncrementalSync */ false, /* queryArgs */ new Bundle());
// Commit sync position
- cacheMediaCollectionInfo(authority, params.latestMediaCollectionInfo);
+ cacheMediaCollectionInfo(authority, isLocal, params.latestMediaCollectionInfo);
break;
case SYNC_TYPE_MEDIA_INCREMENTAL:
final Bundle queryArgs = new Bundle();
queryArgs.putLong(EXTRA_SYNC_GENERATION, params.syncGeneration);
- executeSyncAdd(authority, params.getMediaCollectionId(),
+ executeSyncAdd(authority, isLocal, params.getMediaCollectionId(),
/* isIncrementalSync */ true, queryArgs);
- executeSyncRemove(authority, params.getMediaCollectionId(), queryArgs);
+ executeSyncRemove(authority, isLocal, params.getMediaCollectionId(), queryArgs);
// Commit sync position
- cacheMediaCollectionInfo(authority, params.latestMediaCollectionInfo);
+ cacheMediaCollectionInfo(authority, isLocal, params.latestMediaCollectionInfo);
break;
case SYNC_TYPE_NONE:
break;
@@ -492,33 +516,40 @@ public class PickerSyncController {
}
} catch (RuntimeException e) {
// Reset all media for the cloud provider in case it never succeeds
- resetAllMedia(authority);
+ resetAllMedia(authority, isLocal);
// Attempt a full sync. If this fails, the db table would have been reset,
// flushing all old content and leaving the picker UI empty.
Log.e(TAG, "Failed to sync all media. Reset media and retry: " + retryOnFailure, e);
if (retryOnFailure) {
- syncAllMediaFromProvider(authority, /* retryOnFailure */ false);
+ syncAllMediaFromProvider(authority, isLocal, /* retryOnFailure */ false);
}
+ } finally {
+ Trace.endSection();
}
}
- private void executeSyncReset(String authority) {
- Log.i(TAG, "Executing SyncReset. authority: " + authority);
+ private void executeSyncReset(String authority, boolean isLocal) {
+ Log.i(TAG, "Executing SyncReset. isLocal: " + isLocal + ". authority: " + authority);
+ Trace.beginSection(traceSectionName("executeSyncReset", isLocal));
try (PickerDbFacade.DbWriteOperation operation =
mDbFacade.beginResetMediaOperation(authority)) {
final int writeCount = operation.execute(null /* cursor */);
operation.setSuccess();
- Log.i(TAG, "SyncReset. Authority: " + authority + ". Result count: " + writeCount);
+ Log.i(TAG, "SyncReset. isLocal:" + isLocal + ". authority: " + authority
+ + ". result count: " + writeCount);
+ } finally {
+ Trace.endSection();
}
}
- private void executeSyncAlbumReset(String authority, String albumId) {
- Log.i(TAG, "Executing SyncAlbumReset. authority: " + authority + ". albumId: "
- + albumId);
+ private void executeSyncAlbumReset(String authority, boolean isLocal, String albumId) {
+ Log.i(TAG, "Executing SyncAlbumReset."
+ + " isLocal: " + isLocal + ". authority: " + authority + ". albumId: " + albumId);
+ Trace.beginSection(traceSectionName("executeSyncAlbumReset", isLocal));
try (PickerDbFacade.DbWriteOperation operation =
mDbFacade.beginResetAlbumMediaOperation(authority, albumId)) {
final int writeCount = operation.execute(null /* cursor */);
@@ -526,29 +557,39 @@ public class PickerSyncController {
Log.i(TAG, "Successfully executed SyncResetAlbum. authority: " + authority
+ ". albumId: " + albumId + ". Result count: " + writeCount);
+ } finally {
+ Trace.endSection();
}
}
- private void executeSyncAdd(String authority, String expectedMediaCollectionId,
- boolean isIncrementalSync, Bundle queryArgs) {
+ private void executeSyncAdd(String authority, boolean isLocal,
+ String expectedMediaCollectionId, boolean isIncrementalSync, Bundle queryArgs) {
final Uri uri = getMediaUri(authority);
final List<String> expectedHonoredArgs = new ArrayList<>();
if (isIncrementalSync) {
expectedHonoredArgs.add(EXTRA_SYNC_GENERATION);
}
- Log.i(TAG, "Executing SyncAdd. authority: " + authority);
+ Log.i(TAG, "Executing SyncAdd. isLocal: " + isLocal + ". authority: " + authority);
+
+ Trace.beginSection(traceSectionName("executeSyncAdd", isLocal));
try (PickerDbFacade.DbWriteOperation operation =
mDbFacade.beginAddMediaOperation(authority)) {
executePagedSync(uri, expectedMediaCollectionId, expectedHonoredArgs, queryArgs,
operation);
+ } finally {
+ Trace.endSection();
}
}
- private void executeSyncAddAlbum(String authority, String albumId, Bundle queryArgs) {
+ private void executeSyncAddAlbum(String authority, boolean isLocal,
+ String albumId, Bundle queryArgs) {
final Uri uri = getMediaUri(authority);
- Log.i(TAG, "Executing SyncAddAlbum. authority: " + authority + ". albumId: " + albumId);
+ Log.i(TAG, "Executing SyncAddAlbum. "
+ + "isLocal: " + isLocal + ". authority: " + authority + ". albumId: " + albumId);
+
+ Trace.beginSection(traceSectionName("executeSyncAddAlbum", isLocal));
try (PickerDbFacade.DbWriteOperation operation =
mDbFacade.beginAddAlbumMediaOperation(authority, albumId)) {
@@ -556,17 +597,24 @@ public class PickerSyncController {
// always a full sync
executePagedSync(uri, /* mediaCollectionId */ null, Arrays.asList(EXTRA_ALBUM_ID),
queryArgs, operation);
+ } finally {
+ Trace.endSection();
}
}
- private void executeSyncRemove(String authority, String mediaCollectionId, Bundle queryArgs) {
+ private void executeSyncRemove(String authority, boolean isLocal,
+ String mediaCollectionId, Bundle queryArgs) {
final Uri uri = getDeletedMediaUri(authority);
- Log.i(TAG, "Executing SyncRemove. authority: " + authority);
+ Log.i(TAG, "Executing SyncRemove. isLocal: " + isLocal + ". authority: " + authority);
+
+ Trace.beginSection(traceSectionName("executeSyncRemove", isLocal));
try (PickerDbFacade.DbWriteOperation operation =
mDbFacade.beginRemoveMediaOperation(authority)) {
executePagedSync(uri, mediaCollectionId, Arrays.asList(EXTRA_SYNC_GENERATION),
queryArgs, operation);
+ } finally {
+ Trace.endSection();
}
}
@@ -602,47 +650,45 @@ public class PickerSyncController {
Log.d(TAG, "Updated cloud provider to: " + authority);
}
- private void cacheMediaCollectionInfo(String authority, Bundle bundle) {
+ private void cacheMediaCollectionInfo(String authority, boolean isLocal, Bundle bundle) {
if (authority == null) {
Log.d(TAG, "Ignoring cache media info for null authority with bundle: " + bundle);
return;
}
- final SharedPreferences.Editor editor = mSyncPrefs.edit();
-
- if (bundle == null) {
- editor.remove(getPrefsKey(authority, MediaCollectionInfo.MEDIA_COLLECTION_ID));
- editor.remove(getPrefsKey(authority, MediaCollectionInfo.LAST_MEDIA_SYNC_GENERATION));
- } else {
- final String collectionId = bundle.getString(MediaCollectionInfo.MEDIA_COLLECTION_ID);
- final long generation = bundle.getLong(
- MediaCollectionInfo.LAST_MEDIA_SYNC_GENERATION);
-
- editor.putString(getPrefsKey(authority, MediaCollectionInfo.MEDIA_COLLECTION_ID),
- collectionId);
- editor.putLong(getPrefsKey(authority, MediaCollectionInfo.LAST_MEDIA_SYNC_GENERATION),
- generation);
+ Trace.beginSection(traceSectionName("cacheMediaCollectionInfo", isLocal));
+ try {
+ final SharedPreferences.Editor editor = mSyncPrefs.edit();
+ if (bundle == null) {
+ editor.remove(getPrefsKey(isLocal, MEDIA_COLLECTION_ID));
+ editor.remove(getPrefsKey(isLocal, LAST_MEDIA_SYNC_GENERATION));
+ } else {
+ final String collectionId = bundle.getString(MEDIA_COLLECTION_ID);
+ final long generation = bundle.getLong(LAST_MEDIA_SYNC_GENERATION);
+
+ editor.putString(getPrefsKey(isLocal, MEDIA_COLLECTION_ID), collectionId);
+ editor.putLong(getPrefsKey(isLocal, LAST_MEDIA_SYNC_GENERATION), generation);
+ }
+ editor.apply();
+ } finally {
+ Trace.endSection();
}
-
- editor.apply();
}
- private void resetCachedMediaCollectionInfo(String authority) {
- cacheMediaCollectionInfo(authority, /* bundle */ null);
+ private void resetCachedMediaCollectionInfo(String authority, boolean isLocal) {
+ cacheMediaCollectionInfo(authority, isLocal, /* bundle */ null);
}
- private Bundle getCachedMediaCollectionInfo(String authority) {
+ private Bundle getCachedMediaCollectionInfo(boolean isLocal) {
final Bundle bundle = new Bundle();
final String collectionId = mSyncPrefs.getString(
- getPrefsKey(authority, MediaCollectionInfo.MEDIA_COLLECTION_ID),
- /* default */ null);
+ getPrefsKey(isLocal, MEDIA_COLLECTION_ID), /* default */ null);
final long generation = mSyncPrefs.getLong(
- getPrefsKey(authority, MediaCollectionInfo.LAST_MEDIA_SYNC_GENERATION),
- /* default */ -1);
+ getPrefsKey(isLocal, LAST_MEDIA_SYNC_GENERATION), /* default */ -1);
- bundle.putString(MediaCollectionInfo.MEDIA_COLLECTION_ID, collectionId);
- bundle.putLong(MediaCollectionInfo.LAST_MEDIA_SYNC_GENERATION, generation);
+ bundle.putString(MEDIA_COLLECTION_ID, collectionId);
+ bundle.putLong(LAST_MEDIA_SYNC_GENERATION, generation);
return bundle;
}
@@ -654,27 +700,24 @@ public class PickerSyncController {
}
@SyncType
- private SyncRequestParams getSyncRequestParams(String authority) {
+ private SyncRequestParams getSyncRequestParams(String authority, boolean isLocal) {
if (authority == null) {
// Only cloud authority can be null
Log.d(TAG, "Fetching SyncRequestParams. Null cloud authority. Result: SYNC_TYPE_RESET");
return SyncRequestParams.forResetMedia();
}
- final Bundle cachedMediaCollectionInfo = getCachedMediaCollectionInfo(authority);
+ final Bundle cachedMediaCollectionInfo = getCachedMediaCollectionInfo(isLocal);
final Bundle latestMediaCollectionInfo = getLatestMediaCollectionInfo(authority);
- final String latestCollectionId =
- latestMediaCollectionInfo.getString(MediaCollectionInfo.MEDIA_COLLECTION_ID);
- final long latestGeneration =
- latestMediaCollectionInfo.getLong(MediaCollectionInfo.LAST_MEDIA_SYNC_GENERATION);
+ final String latestCollectionId = latestMediaCollectionInfo.getString(MEDIA_COLLECTION_ID);
+ final long latestGeneration = latestMediaCollectionInfo.getLong(LAST_MEDIA_SYNC_GENERATION);
- final String cachedCollectionId =
- cachedMediaCollectionInfo.getString(MediaCollectionInfo.MEDIA_COLLECTION_ID);
- final long cachedGeneration = cachedMediaCollectionInfo.getLong(
- MediaCollectionInfo.LAST_MEDIA_SYNC_GENERATION);
+ final String cachedCollectionId = cachedMediaCollectionInfo.getString(MEDIA_COLLECTION_ID);
+ final long cachedGeneration = cachedMediaCollectionInfo.getLong(LAST_MEDIA_SYNC_GENERATION);
- Log.d(TAG, "Fetching SyncRequestParams. Authority: " + authority
+ Log.d(TAG, "Fetching SyncRequestParams. Islocal: " + isLocal
+ + ". Authority: " + authority
+ ". LatestMediaCollectionInfo: " + latestMediaCollectionInfo
+ ". CachedMediaCollectionInfo: " + cachedMediaCollectionInfo);
@@ -684,26 +727,24 @@ public class PickerSyncController {
}
if (!Objects.equals(latestCollectionId, cachedCollectionId)) {
- Log.d(TAG, "SyncRequestParams. Authority: " + authority + ". Result: SYNC_TYPE_FULL");
+ Log.d(TAG, "SyncRequestParams. Islocal: " + isLocal + ". Authority: " + authority
+ + ". Result: SYNC_TYPE_FULL");
return SyncRequestParams.forFullMedia(latestMediaCollectionInfo);
}
if (cachedGeneration == latestGeneration) {
- Log.d(TAG, "SyncRequestParams. Authority: " + authority + ". Result: SYNC_TYPE_NONE");
+ Log.d(TAG, "SyncRequestParams. Islocal: " + isLocal + ". Authority: " + authority
+ + ". Result: SYNC_TYPE_NONE");
return SyncRequestParams.forNone();
}
- Log.d(TAG, "SyncRequestParams. Authority: " + authority
+ Log.d(TAG, "SyncRequestParams. Islocal: " + isLocal + ". Authority: " + authority
+ ". Result: SYNC_TYPE_INCREMENTAL");
return SyncRequestParams.forIncremental(cachedGeneration, latestMediaCollectionInfo);
}
- private String getPrefsKey(String authority, String key) {
- return (isLocal(authority) ? PREFS_KEY_LOCAL_PREFIX : PREFS_KEY_CLOUD_PREFIX) + key;
- }
-
- private boolean isLocal(String authority) {
- return mLocalProvider.equals(authority);
+ private String getPrefsKey(boolean isLocal, String key) {
+ return (isLocal ? PREFS_KEY_LOCAL_PREFIX : PREFS_KEY_CLOUD_PREFIX) + key;
}
private Cursor query(Uri uri, Bundle extras) {
@@ -714,31 +755,36 @@ public class PickerSyncController {
private void executePagedSync(Uri uri, String expectedMediaCollectionId,
List<String> expectedHonoredArgs, Bundle queryArgs,
PickerDbFacade.DbWriteOperation dbWriteOperation) {
- int cursorCount = 0;
- int totalRowcount = 0;
- // Set to check the uniqueness of tokens across pages.
- Set<String> tokens = new ArraySet<>();
-
- String nextPageToken = null;
- do {
- if (nextPageToken != null) {
- queryArgs.putString(EXTRA_PAGE_TOKEN, nextPageToken);
- }
+ Trace.beginSection(traceSectionName("executePagedSync"));
+ try {
+ int cursorCount = 0;
+ int totalRowcount = 0;
+ // Set to check the uniqueness of tokens across pages.
+ Set<String> tokens = new ArraySet<>();
+
+ String nextPageToken = null;
+ do {
+ if (nextPageToken != null) {
+ queryArgs.putString(EXTRA_PAGE_TOKEN, nextPageToken);
+ }
- try (Cursor cursor = query(uri, queryArgs)) {
- nextPageToken = validateCursor(cursor, expectedMediaCollectionId,
- expectedHonoredArgs, tokens);
+ try (Cursor cursor = query(uri, queryArgs)) {
+ nextPageToken = validateCursor(cursor, expectedMediaCollectionId,
+ expectedHonoredArgs, tokens);
- int writeCount = dbWriteOperation.execute(cursor);
+ int writeCount = dbWriteOperation.execute(cursor);
- totalRowcount += writeCount;
- cursorCount += cursor.getCount();
- }
- } while (nextPageToken != null);
+ totalRowcount += writeCount;
+ cursorCount += cursor.getCount();
+ }
+ } while (nextPageToken != null);
- dbWriteOperation.setSuccess();
- Log.i(TAG, "Paged sync successful. QueryArgs: " + queryArgs + ". Result count: "
- + totalRowcount + ". Cursor count: " + cursorCount);
+ dbWriteOperation.setSuccess();
+ Log.i(TAG, "Paged sync successful. QueryArgs: " + queryArgs + ". Result count: "
+ + totalRowcount + ". Cursor count: " + cursorCount);
+ } finally {
+ Trace.endSection();
+ }
}
/**
@@ -797,6 +843,15 @@ public class PickerSyncController {
/* defaultValue */ false);
}
+ private static String traceSectionName(@NonNull String method) {
+ return "PSC." + method;
+ }
+
+ private static String traceSectionName(@NonNull String method, boolean isLocal) {
+ return traceSectionName(method)
+ + "[" + (isLocal ? "local" : "cloud") + ']';
+ }
+
private static String validateCursor(Cursor cursor, String expectedMediaCollectionId,
List<String> expectedHonoredArgs, Set<String> usedPageTokens) {
final Bundle bundle = cursor.getExtras();
@@ -857,7 +912,7 @@ public class PickerSyncController {
}
String getMediaCollectionId() {
- return latestMediaCollectionInfo.getString(MediaCollectionInfo.MEDIA_COLLECTION_ID);
+ return latestMediaCollectionInfo.getString(MEDIA_COLLECTION_ID);
}
static SyncRequestParams forNone() {
diff --git a/src/com/android/providers/media/photopicker/data/PickerDbFacade.java b/src/com/android/providers/media/photopicker/data/PickerDbFacade.java
index 7549f21ab..b41af8ab6 100644
--- a/src/com/android/providers/media/photopicker/data/PickerDbFacade.java
+++ b/src/com/android/providers/media/photopicker/data/PickerDbFacade.java
@@ -37,6 +37,7 @@ import android.database.sqlite.SQLiteConstraintException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
+import android.os.Trace;
import android.provider.CloudMediaProviderContract;
import android.provider.MediaStore;
import android.text.TextUtils;
@@ -284,7 +285,14 @@ public class PickerDbFacade {
if (!mDatabase.inTransaction()) {
throw new IllegalStateException("No ongoing DB transaction.");
}
- return executeInternal(cursor);
+ final String traceSectionName = getClass().getSimpleName()
+ + ".execute[" + (mIsLocal ? "local" : "cloud") + ']';
+ Trace.beginSection(traceSectionName);
+ try {
+ return executeInternal(cursor);
+ } finally {
+ Trace.endSection();
+ }
}
public void setSuccess() {
diff --git a/src/com/android/providers/media/scan/ModernMediaScanner.java b/src/com/android/providers/media/scan/ModernMediaScanner.java
index 5afe15e1f..177013658 100644
--- a/src/com/android/providers/media/scan/ModernMediaScanner.java
+++ b/src/com/android/providers/media/scan/ModernMediaScanner.java
@@ -349,7 +349,7 @@ public class ModernMediaScanner implements MediaScanner {
public Scan(File root, int reason, @Nullable String ownerPackage)
throws FileNotFoundException {
- Trace.beginSection("ctor");
+ Trace.beginSection("Scanner.ctor");
mClient = mContext.getContentResolver()
.acquireContentProviderClient(MediaStore.AUTHORITY);
@@ -417,7 +417,7 @@ public class ModernMediaScanner implements MediaScanner {
shouldScanPathAndIsPathHidden(mSingleFile ? mRoot.getParentFile() : mRoot);
if (isDirScannableAndHidden.first) {
// This directory is scannable.
- Trace.beginSection("walkFileTree");
+ Trace.beginSection("Scanner.walkFileTree");
if (isDirScannableAndHidden.second) {
// This directory is hidden
@@ -491,7 +491,7 @@ public class ModernMediaScanner implements MediaScanner {
// The query phase is split from the delete phase so that our query
// remains stable if we need to paginate across multiple windows.
mSignal.throwIfCanceled();
- Trace.beginSection("reconcile");
+ Trace.beginSection("Scanner.reconcile");
// Ignore abstract playlists which don't have files on disk
final String formatClause = "ifnull(" + FileColumns.FORMAT + ","
@@ -546,7 +546,7 @@ public class ModernMediaScanner implements MediaScanner {
// Third, clean all the unknown database entries found above
mSignal.throwIfCanceled();
- Trace.beginSection("clean");
+ Trace.beginSection("Scanner.clean");
try {
for (int i = 0; i < mUnknownIds.size(); i++) {
final long id = mUnknownIds.get(i);
@@ -595,7 +595,7 @@ public class ModernMediaScanner implements MediaScanner {
* and confuse each other.
*/
private void acquireDirectoryLock(@NonNull Path dir) {
- Trace.beginSection("acquireDirectoryLock");
+ Trace.beginSection("Scanner.acquireDirectoryLock");
DirectoryLock lock;
synchronized (mDirectoryLocks) {
lock = mDirectoryLocks.get(dir);
@@ -616,7 +616,7 @@ public class ModernMediaScanner implements MediaScanner {
* structures if no other threads are waiting.
*/
private void releaseDirectoryLock(@NonNull Path dir) {
- Trace.beginSection("releaseDirectoryLock");
+ Trace.beginSection("Scanner.releaseDirectoryLock");
DirectoryLock lock;
synchronized (mDirectoryLocks) {
lock = mDirectoryLocks.get(dir);
@@ -718,7 +718,7 @@ public class ModernMediaScanner implements MediaScanner {
int actualMediaType = mediaTypeFromMimeType(
realFile, actualMimeType, FileColumns.MEDIA_TYPE_NONE);
- Trace.beginSection("checkChanged");
+ Trace.beginSection("Scanner.checkChanged");
final Bundle queryArgs = new Bundle();
queryArgs.putString(ContentResolver.QUERY_ARG_SQL_SELECTION,
@@ -789,7 +789,7 @@ public class ModernMediaScanner implements MediaScanner {
}
final ContentProviderOperation.Builder op;
- Trace.beginSection("scanItem");
+ Trace.beginSection("Scanner.scanItem");
try {
op = scanItem(existingId, realFile, attrs, actualMimeType, actualMediaType,
mVolumeName);
@@ -910,7 +910,7 @@ public class ModernMediaScanner implements MediaScanner {
// Bail early when nothing pending
if (mPending.isEmpty()) return;
- Trace.beginSection("applyPending");
+ Trace.beginSection("Scanner.applyPending");
try {
ContentProviderResult[] results = mResolver.applyBatch(AUTHORITY, mPending);
for (int index = 0; index < results.length; index++) {
@@ -1626,7 +1626,7 @@ public class ModernMediaScanner implements MediaScanner {
* path should be considered hidden.
*/
static Pair<Boolean, Boolean> shouldScanPathAndIsPathHidden(@NonNull File dir) {
- Trace.beginSection("shouldScanPathAndIsPathHiodden");
+ Trace.beginSection("Scanner.shouldScanPathAndIsPathHidden");
try {
boolean isPathHidden = false;
while (dir != null) {
diff --git a/src/com/android/providers/media/util/DatabaseUtils.java b/src/com/android/providers/media/util/DatabaseUtils.java
index cec6f27f1..e83d05c98 100644
--- a/src/com/android/providers/media/util/DatabaseUtils.java
+++ b/src/com/android/providers/media/util/DatabaseUtils.java
@@ -48,7 +48,6 @@ import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
import java.util.Locale;
import java.util.function.Consumer;
@@ -451,7 +450,7 @@ public class DatabaseUtils {
public static long executeInsert(@NonNull SQLiteDatabase db, @NonNull String sql,
@Nullable Object[] bindArgs) throws SQLException {
- Trace.beginSection("executeInsert");
+ Trace.beginSection("DbUtils.executeInsert");
try (SQLiteStatement st = db.compileStatement(sql)) {
bindArgs(st, bindArgs);
return st.executeInsert();
@@ -462,7 +461,7 @@ public class DatabaseUtils {
public static int executeUpdateDelete(@NonNull SQLiteDatabase db, @NonNull String sql,
@Nullable Object[] bindArgs) throws SQLException {
- Trace.beginSection("executeUpdateDelete");
+ Trace.beginSection("DbUtils.executeUpdateDelete");
try (SQLiteStatement st = db.compileStatement(sql)) {
bindArgs(st, bindArgs);
return st.executeUpdateDelete();
diff --git a/src/com/android/providers/media/util/SpecialFormatDetector.java b/src/com/android/providers/media/util/SpecialFormatDetector.java
index d8d65d94e..a8569d746 100644
--- a/src/com/android/providers/media/util/SpecialFormatDetector.java
+++ b/src/com/android/providers/media/util/SpecialFormatDetector.java
@@ -29,9 +29,9 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
+import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
-import java.io.File;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
@@ -143,7 +143,7 @@ public class SpecialFormatDetector {
return false;
}
- Trace.beginSection("motionPhotoDetectionUsingXpp");
+ Trace.beginSection("FormatDetector.motionPhotoDetectionUsingXpp");
try {
return isMotionPhoto(xpp);
} finally {
diff --git a/src/com/android/providers/media/util/XAttrUtils.java b/src/com/android/providers/media/util/XAttrUtils.java
index 236f7ed13..31dbe8ab7 100644
--- a/src/com/android/providers/media/util/XAttrUtils.java
+++ b/src/com/android/providers/media/util/XAttrUtils.java
@@ -62,7 +62,7 @@ public class XAttrUtils {
public static Optional<FileAccessAttributes> getFileAttributesFromXAttr(String path,
String key) {
- Trace.beginSection("getFileAttributesFromXAttr");
+ Trace.beginSection("XAttrUtils.getFileAttributesFromXAttr");
String relativePathWithDisplayName = DATA_MEDIA_XATTR_DIRECTORY_PATH + "/"
+ extractRelativePath(path) + extractDisplayName(path);
try {
diff --git a/trace.sh b/trace.sh
index 410e8f073..57e58cd6a 100755
--- a/trace.sh
+++ b/trace.sh
@@ -1 +1,3 @@
-./external/chromium-trace/systrace.py -b 128768 -a com.google.android.providers.media.module,com.android.providers.media.module binder_driver
+$ANDROID_BUILD_TOP/external/perfetto/tools/record_android_trace \
+ -c $ANDROID_BUILD_TOP/packages/providers/MediaProvider/perfetto_config.pbtx \
+ -o /tmp/perfetto-traces/$(date +"%d-%m-%Y_%H-%M-%S").perfetto-trace