Request all metadata for Images plugin before export
Summary:
Fresco plugin on the desktop side used to ask for all the image list along with the metadata when it was mounted. The mobile side never sent the image list and other information if not requested from it. That means, although Fresco plugin is a background plugin, there weren't any messages sent from the mobile side. Thus there was no trace available for Images plugin when the trace was exported. This diff, adds a hook which gets called before the export, where we request all the metadata from the mobile SDK.
BUG:
{F159305887}
Reviewed By: passy
Differential Revision: D15407962
fbshipit-source-id: 0012de2ab29d0f62e92d00f4926b04b1e394b62a
This commit is contained in:
committed by
Facebook Github Bot
parent
7576e1c61d
commit
914cbf6ccd
@@ -35,8 +35,12 @@ import com.facebook.imagepipeline.debug.DebugImageTracker;
|
|||||||
import com.facebook.imagepipeline.debug.FlipperImageTracker;
|
import com.facebook.imagepipeline.debug.FlipperImageTracker;
|
||||||
import com.facebook.imagepipeline.image.CloseableBitmap;
|
import com.facebook.imagepipeline.image.CloseableBitmap;
|
||||||
import com.facebook.imagepipeline.image.CloseableImage;
|
import com.facebook.imagepipeline.image.CloseableImage;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -70,6 +74,7 @@ public class FrescoFlipperPlugin extends BufferingFlipperPlugin implements Image
|
|||||||
private final DebugMemoryManager mMemoryManager;
|
private final DebugMemoryManager mMemoryManager;
|
||||||
private final FlipperPerfLogger mPerfLogger;
|
private final FlipperPerfLogger mPerfLogger;
|
||||||
@Nullable private final FrescoFlipperDebugPrefHelper mDebugPrefHelper;
|
@Nullable private final FrescoFlipperDebugPrefHelper mDebugPrefHelper;
|
||||||
|
private final List<FlipperObject> mEvents = new ArrayList<>();
|
||||||
|
|
||||||
public FrescoFlipperPlugin(
|
public FrescoFlipperPlugin(
|
||||||
DebugImageTracker imageTracker,
|
DebugImageTracker imageTracker,
|
||||||
@@ -111,7 +116,62 @@ public class FrescoFlipperPlugin extends BufferingFlipperPlugin implements Image
|
|||||||
@Override
|
@Override
|
||||||
public void onConnect(FlipperConnection connection) {
|
public void onConnect(FlipperConnection connection) {
|
||||||
super.onConnect(connection);
|
super.onConnect(connection);
|
||||||
|
connection.receive(
|
||||||
|
"getAllImageData",
|
||||||
|
new FlipperReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(FlipperObject params, FlipperResponder responder) {
|
||||||
|
if (!ensureFrescoInitialized(responder)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final ImagePipelineFactory imagePipelineFactory = Fresco.getImagePipelineFactory();
|
||||||
|
final CountingMemoryCacheInspector.DumpInfo memoryCache =
|
||||||
|
new CountingMemoryCacheInspector<>(
|
||||||
|
imagePipelineFactory.getBitmapCountingMemoryCache())
|
||||||
|
.dumpCacheContent();
|
||||||
|
|
||||||
|
final FlipperArray memoryCacheSharedEntries = buildImageIdList(memoryCache.sharedEntries);
|
||||||
|
final FlipperArray memoryCacheLRUEntries = buildImageIdList(memoryCache.lruEntries);
|
||||||
|
final FlipperArray.Builder imageIDListBuilder = new FlipperArray.Builder();
|
||||||
|
for (int i = 0; i < memoryCacheSharedEntries.length(); ++i) {
|
||||||
|
final String imageID = memoryCacheSharedEntries.getString(i);
|
||||||
|
imageIDListBuilder.put(imageID);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < memoryCacheLRUEntries.length(); ++i) {
|
||||||
|
final String imageID = memoryCacheLRUEntries.getString(i);
|
||||||
|
imageIDListBuilder.put(imageID);
|
||||||
|
}
|
||||||
|
final FlipperArray imageIDs = imageIDListBuilder.build();
|
||||||
|
final FlipperObject levels =
|
||||||
|
getImageList(memoryCache, memoryCacheSharedEntries, memoryCacheLRUEntries);
|
||||||
|
final FlipperArray.Builder imageDataListBuilder = new FlipperArray.Builder();
|
||||||
|
|
||||||
|
for (int i = 0; i < imageIDs.length(); ++i) {
|
||||||
|
final String imageID = imageIDs.getString(i);
|
||||||
|
final CacheKey cacheKey = mFlipperImageTracker.getCacheKey(imageID);
|
||||||
|
if (cacheKey == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final CloseableReference<CloseableImage> ref =
|
||||||
|
imagePipelineFactory.getBitmapCountingMemoryCache().get(cacheKey);
|
||||||
|
if (ref == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final CloseableBitmap bitmap = (CloseableBitmap) ref.get();
|
||||||
|
final String encodedBitmap =
|
||||||
|
bitmapToBase64Preview(bitmap.getUnderlyingBitmap(), mPlatformBitmapFactory);
|
||||||
|
imageDataListBuilder.put(
|
||||||
|
getImageData(
|
||||||
|
imageID, encodedBitmap, bitmap, mFlipperImageTracker.getUriString(cacheKey)));
|
||||||
|
}
|
||||||
|
responder.success(
|
||||||
|
new FlipperObject.Builder()
|
||||||
|
.put("levels", levels)
|
||||||
|
.put("imageDataList", imageDataListBuilder.build())
|
||||||
|
.put("events", new FlipperArray(new JSONArray(mEvents)))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
});
|
||||||
connection.receive(
|
connection.receive(
|
||||||
"listImages",
|
"listImages",
|
||||||
new FlipperReceiver() {
|
new FlipperReceiver() {
|
||||||
@@ -127,29 +187,11 @@ public class FrescoFlipperPlugin extends BufferingFlipperPlugin implements Image
|
|||||||
new CountingMemoryCacheInspector<>(
|
new CountingMemoryCacheInspector<>(
|
||||||
imagePipelineFactory.getBitmapCountingMemoryCache())
|
imagePipelineFactory.getBitmapCountingMemoryCache())
|
||||||
.dumpCacheContent();
|
.dumpCacheContent();
|
||||||
|
|
||||||
responder.success(
|
responder.success(
|
||||||
new FlipperObject.Builder()
|
getImageList(
|
||||||
.put(
|
memoryCache,
|
||||||
"levels",
|
buildImageIdList(memoryCache.sharedEntries),
|
||||||
new FlipperArray.Builder()
|
buildImageIdList(memoryCache.lruEntries)));
|
||||||
.put(
|
|
||||||
new FlipperObject.Builder()
|
|
||||||
.put("cacheType", "On screen bitmaps")
|
|
||||||
.put("sizeBytes", memoryCache.size - memoryCache.lruSize)
|
|
||||||
.put("imageIds", buildImageIdList(memoryCache.sharedEntries))
|
|
||||||
.build())
|
|
||||||
.put(
|
|
||||||
new FlipperObject.Builder()
|
|
||||||
.put("cacheType", "Bitmap memory cache")
|
|
||||||
.put("clearKey", "memory")
|
|
||||||
.put("sizeBytes", memoryCache.size)
|
|
||||||
.put("maxSizeBytes", memoryCache.maxSize)
|
|
||||||
.put("imageIds", buildImageIdList(memoryCache.lruEntries))
|
|
||||||
.build())
|
|
||||||
// TODO (t31947642): list images on disk
|
|
||||||
.build())
|
|
||||||
.build());
|
|
||||||
mPerfLogger.endMarker("Sonar.Fresco.listImages");
|
mPerfLogger.endMarker("Sonar.Fresco.listImages");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -185,14 +227,8 @@ public class FrescoFlipperPlugin extends BufferingFlipperPlugin implements Image
|
|||||||
bitmapToBase64Preview(bitmap.getUnderlyingBitmap(), mPlatformBitmapFactory);
|
bitmapToBase64Preview(bitmap.getUnderlyingBitmap(), mPlatformBitmapFactory);
|
||||||
|
|
||||||
responder.success(
|
responder.success(
|
||||||
new FlipperObject.Builder()
|
getImageData(
|
||||||
.put("imageId", imageId)
|
imageId, encodedBitmap, bitmap, mFlipperImageTracker.getUriString(cacheKey)));
|
||||||
.put("uri", mFlipperImageTracker.getUriString(cacheKey))
|
|
||||||
.put("width", bitmap.getWidth())
|
|
||||||
.put("height", bitmap.getHeight())
|
|
||||||
.put("sizeBytes", bitmap.getSizeInBytes())
|
|
||||||
.put("data", encodedBitmap)
|
|
||||||
.build());
|
|
||||||
|
|
||||||
mPerfLogger.endMarker("Sonar.Fresco.getImage");
|
mPerfLogger.endMarker("Sonar.Fresco.getImage");
|
||||||
}
|
}
|
||||||
@@ -266,6 +302,45 @@ public class FrescoFlipperPlugin extends BufferingFlipperPlugin implements Image
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private FlipperObject getImageList(
|
||||||
|
CountingMemoryCacheInspector.DumpInfo memoryCache,
|
||||||
|
FlipperArray memoryCacheSharedEntries,
|
||||||
|
FlipperArray memoryCacheLRUEntries) {
|
||||||
|
return new FlipperObject.Builder()
|
||||||
|
.put(
|
||||||
|
"levels",
|
||||||
|
new FlipperArray.Builder()
|
||||||
|
.put(
|
||||||
|
new FlipperObject.Builder()
|
||||||
|
.put("cacheType", "On screen bitmaps")
|
||||||
|
.put("sizeBytes", memoryCache.size - memoryCache.lruSize)
|
||||||
|
.put("imageIds", memoryCacheSharedEntries)
|
||||||
|
.build())
|
||||||
|
.put(
|
||||||
|
new FlipperObject.Builder()
|
||||||
|
.put("cacheType", "Bitmap memory cache")
|
||||||
|
.put("clearKey", "memory")
|
||||||
|
.put("sizeBytes", memoryCache.size)
|
||||||
|
.put("maxSizeBytes", memoryCache.maxSize)
|
||||||
|
.put("imageIds", memoryCacheLRUEntries)
|
||||||
|
.build())
|
||||||
|
// TODO (t31947642): list images on disk
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private FlipperObject getImageData(
|
||||||
|
String imageID, String encodedBitmap, CloseableBitmap bitmap, String uriString) {
|
||||||
|
return new FlipperObject.Builder()
|
||||||
|
.put("imageId", imageID)
|
||||||
|
.put("uri", uriString)
|
||||||
|
.put("width", bitmap.getWidth())
|
||||||
|
.put("height", bitmap.getHeight())
|
||||||
|
.put("sizeBytes", bitmap.getSizeInBytes())
|
||||||
|
.put("data", encodedBitmap)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
private boolean ensureFrescoInitialized(FlipperResponder responder) {
|
private boolean ensureFrescoInitialized(FlipperResponder responder) {
|
||||||
mPerfLogger.startMarker("Sonar.Fresco.ensureFrescoInitialized");
|
mPerfLogger.startMarker("Sonar.Fresco.ensureFrescoInitialized");
|
||||||
try {
|
try {
|
||||||
@@ -403,8 +478,9 @@ public class FrescoFlipperPlugin extends BufferingFlipperPlugin implements Image
|
|||||||
.put("height", imagePerfData.getOnScreenHeightPx())
|
.put("height", imagePerfData.getOnScreenHeightPx())
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
FlipperObject responseObject = response.build();
|
||||||
send(FRESCO_EVENT, response.build());
|
mEvents.add(responseObject);
|
||||||
|
send(FRESCO_EVENT, responseObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onImageVisibilityUpdated(ImagePerfData imagePerfData, int visibilityState) {
|
public void onImageVisibilityUpdated(ImagePerfData imagePerfData, int visibilityState) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// This source code is licensed under the MIT license found in the LICENSE file
|
// This source code is licensed under the MIT license found in the LICENSE file
|
||||||
// in the root directory of this source tree.
|
// in the root directory of this source tree.
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import type {
|
|||||||
CacheInfo,
|
CacheInfo,
|
||||||
} from './api.js';
|
} from './api.js';
|
||||||
import type {ImagesMap} from './ImagePool.js';
|
import type {ImagesMap} from './ImagePool.js';
|
||||||
import type {MetricType} from 'flipper';
|
import type {MetricType, MiddlewareAPI} from 'flipper';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ImagesCacheOverview from './ImagesCacheOverview.js';
|
import ImagesCacheOverview from './ImagesCacheOverview.js';
|
||||||
import {
|
import {
|
||||||
@@ -65,6 +65,12 @@ const debugLog = (...args) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type ImagesMetaData = {|
|
||||||
|
levels: ImagesListResponse,
|
||||||
|
events: Array<ImageEventWithId>,
|
||||||
|
imageDataList: Array<ImageData>,
|
||||||
|
|};
|
||||||
|
|
||||||
export default class extends FlipperPlugin<PluginState, *, PersistedState> {
|
export default class extends FlipperPlugin<PluginState, *, PersistedState> {
|
||||||
static defaultPersistedState: PersistedState = {
|
static defaultPersistedState: PersistedState = {
|
||||||
images: [],
|
images: [],
|
||||||
@@ -73,6 +79,52 @@ export default class extends FlipperPlugin<PluginState, *, PersistedState> {
|
|||||||
surfaceList: new Set(),
|
surfaceList: new Set(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static exportPersistedState = (
|
||||||
|
callClient: (string, ?Object) => Promise<Object>,
|
||||||
|
persistedState: ?PersistedState,
|
||||||
|
store: ?MiddlewareAPI,
|
||||||
|
): Promise<?PersistedState> => {
|
||||||
|
if (persistedState) {
|
||||||
|
return Promise.resolve(persistedState);
|
||||||
|
}
|
||||||
|
const defaultPromise = Promise.resolve(persistedState);
|
||||||
|
if (!store) {
|
||||||
|
return defaultPromise;
|
||||||
|
}
|
||||||
|
return callClient('getAllImageData').then((data: ImagesMetaData) => {
|
||||||
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const {levels, events, imageDataList} = data;
|
||||||
|
let pluginData: PersistedState = {
|
||||||
|
images: [...levels.levels],
|
||||||
|
surfaceList: new Set(),
|
||||||
|
events: [],
|
||||||
|
imagesMap: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
events.forEach((event: ImageEventWithId, index) => {
|
||||||
|
const {attribution} = event;
|
||||||
|
if (attribution instanceof Array && attribution.length > 0) {
|
||||||
|
const surface = attribution[0].trim();
|
||||||
|
if (surface.length > 0) {
|
||||||
|
pluginData.surfaceList.add(surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pluginData = {
|
||||||
|
...pluginData,
|
||||||
|
events: [{eventId: index, ...event}, ...pluginData.events],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
imageDataList.forEach((imageData: ImageData) => {
|
||||||
|
const {imageId} = imageData;
|
||||||
|
pluginData.imagesMap[imageId] = imageData;
|
||||||
|
});
|
||||||
|
return pluginData;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
static metricsReducer = (
|
static metricsReducer = (
|
||||||
persistedState: PersistedState,
|
persistedState: PersistedState,
|
||||||
): Promise<MetricType> => {
|
): Promise<MetricType> => {
|
||||||
@@ -113,42 +165,6 @@ export default class extends FlipperPlugin<PluginState, *, PersistedState> {
|
|||||||
coldStartFilter: false,
|
coldStartFilter: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
init() {
|
|
||||||
debugLog('init()');
|
|
||||||
this.updateCaches('init');
|
|
||||||
this.client.subscribe('events', (event: ImageEvent) => {
|
|
||||||
const {surfaceList} = this.props.persistedState;
|
|
||||||
const {attribution} = event;
|
|
||||||
if (attribution instanceof Array && attribution.length > 0) {
|
|
||||||
const surface = attribution[0].trim();
|
|
||||||
if (surface.length > 0) {
|
|
||||||
surfaceList.add(surface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.props.setPersistedState({
|
|
||||||
events: [
|
|
||||||
{eventId: this.nextEventId, ...event},
|
|
||||||
...this.props.persistedState.events,
|
|
||||||
],
|
|
||||||
});
|
|
||||||
this.nextEventId++;
|
|
||||||
});
|
|
||||||
this.client.subscribe(
|
|
||||||
'debug_overlay_event',
|
|
||||||
(event: FrescoDebugOverlayEvent) => {
|
|
||||||
this.setState({isDebugOverlayEnabled: event.enabled});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
this.imagePool = new ImagePool(this.getImage, (images: ImagesMap) =>
|
|
||||||
this.props.setPersistedState({imagesMap: images}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
teardown() {
|
|
||||||
this.imagePool.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
filterImages = (
|
filterImages = (
|
||||||
images: ImagesList,
|
images: ImagesList,
|
||||||
events: Array<ImageEventWithId>,
|
events: Array<ImageEventWithId>,
|
||||||
@@ -183,6 +199,49 @@ export default class extends FlipperPlugin<PluginState, *, PersistedState> {
|
|||||||
return imageList;
|
return imageList;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
init() {
|
||||||
|
debugLog('init()');
|
||||||
|
this.updateCaches('init');
|
||||||
|
this.client.subscribe('events', (event: ImageEvent) => {
|
||||||
|
const {surfaceList} = this.props.persistedState;
|
||||||
|
const {attribution} = event;
|
||||||
|
if (attribution instanceof Array && attribution.length > 0) {
|
||||||
|
const surface = attribution[0].trim();
|
||||||
|
if (surface.length > 0) {
|
||||||
|
surfaceList.add(surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.props.setPersistedState({
|
||||||
|
events: [
|
||||||
|
{eventId: this.nextEventId, ...event},
|
||||||
|
...this.props.persistedState.events,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
this.nextEventId++;
|
||||||
|
});
|
||||||
|
this.client.subscribe(
|
||||||
|
'debug_overlay_event',
|
||||||
|
(event: FrescoDebugOverlayEvent) => {
|
||||||
|
this.setState({isDebugOverlayEnabled: event.enabled});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
this.imagePool = new ImagePool(this.getImage, (images: ImagesMap) =>
|
||||||
|
this.props.setPersistedState({imagesMap: images}),
|
||||||
|
);
|
||||||
|
|
||||||
|
let images = this.filterImages(
|
||||||
|
this.props.persistedState.images,
|
||||||
|
this.props.persistedState.events,
|
||||||
|
this.state.selectedSurface,
|
||||||
|
this.state.coldStartFilter,
|
||||||
|
);
|
||||||
|
this.setState({images});
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown() {
|
||||||
|
this.imagePool.clear();
|
||||||
|
}
|
||||||
|
|
||||||
updateImagesOnUI = (
|
updateImagesOnUI = (
|
||||||
images: ImagesList,
|
images: ImagesList,
|
||||||
surface: string,
|
surface: string,
|
||||||
|
|||||||
@@ -319,6 +319,15 @@ export function importDataToStore(data: string, store: Store) {
|
|||||||
|
|
||||||
const {pluginStates} = json.store;
|
const {pluginStates} = json.store;
|
||||||
const keys = Object.keys(pluginStates);
|
const keys = Object.keys(pluginStates);
|
||||||
|
keys.forEach(key => {
|
||||||
|
store.dispatch({
|
||||||
|
type: 'SET_PLUGIN_STATE',
|
||||||
|
payload: {
|
||||||
|
pluginKey: key,
|
||||||
|
state: pluginStates[key],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
clients.forEach(client => {
|
clients.forEach(client => {
|
||||||
const clientPlugins = keys
|
const clientPlugins = keys
|
||||||
.filter(key => {
|
.filter(key => {
|
||||||
@@ -340,15 +349,6 @@ export function importDataToStore(data: string, store: Store) {
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
keys.forEach(key => {
|
|
||||||
store.dispatch({
|
|
||||||
type: 'SET_PLUGIN_STATE',
|
|
||||||
payload: {
|
|
||||||
pluginKey: key,
|
|
||||||
state: pluginStates[key],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const importFileToStore = (file: string, store: Store) => {
|
export const importFileToStore = (file: string, store: Store) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user