Move flipper-fresco-plugin to fresco's repo from flipper's repo (#4546)
Summary: Pull Request resolved: https://github.com/facebook/flipper/pull/4546 Move flipper-fresco-plugin to fresco's repo from flipper's repo Reviewed By: passy Differential Revision: D43467895 fbshipit-source-id: efea88563cf931baf4bda0c8bbdfbe41d0f769c5
This commit is contained in:
committed by
Facebook GitHub Bot
parent
11f5330d7c
commit
2e31247486
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
apply plugin: 'com.android.library'
|
|
||||||
|
|
||||||
android {
|
|
||||||
compileSdkVersion rootProject.compileSdkVersion
|
|
||||||
buildToolsVersion rootProject.buildToolsVersion
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
minSdkVersion rootProject.minSdkVersion
|
|
||||||
targetSdkVersion rootProject.targetSdkVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation project(':android')
|
|
||||||
implementation deps.fresco
|
|
||||||
implementation deps.frescoFlipper
|
|
||||||
compileOnly deps.jsr305
|
|
||||||
|
|
||||||
api deps.boltsTasks
|
|
||||||
|
|
||||||
// Exclude the actual stetho dep as we only want some of the fresco APIs here
|
|
||||||
implementation(deps.frescoStetho) {
|
|
||||||
exclude group: 'com.facebook.stetho'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
apply plugin: 'com.vanniktech.maven.publish'
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
#
|
|
||||||
# This source code is licensed under the MIT license found in the LICENSE
|
|
||||||
# file in the root directory of this source tree.
|
|
||||||
#
|
|
||||||
|
|
||||||
POM_NAME=Flipper Fresco Plugin
|
|
||||||
POM_DESCRIPTION=Images plugin for Flipper
|
|
||||||
POM_ARTIFACT_ID=flipper-fresco-plugin
|
|
||||||
POM_PACKAGING=aar
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
~ Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
~
|
|
||||||
~ This source code is licensed under the MIT license found in the LICENSE
|
|
||||||
~ file in the root directory of this source tree.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
package="com.facebook.flipper.plugins.fresco">
|
|
||||||
</manifest>
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.facebook.flipper.plugins.fresco;
|
|
||||||
|
|
||||||
public interface FrescoFlipperDebugPrefHelper {
|
|
||||||
|
|
||||||
interface Listener {
|
|
||||||
void onEnabledStatusChanged(boolean enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDebugOverlayEnabled(boolean enabled);
|
|
||||||
|
|
||||||
boolean isDebugOverlayEnabled();
|
|
||||||
|
|
||||||
void setDebugOverlayEnabledListener(Listener l);
|
|
||||||
}
|
|
||||||
@@ -1,651 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.facebook.flipper.plugins.fresco;
|
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.util.Base64;
|
|
||||||
import android.util.Pair;
|
|
||||||
import bolts.Continuation;
|
|
||||||
import bolts.Task;
|
|
||||||
import com.facebook.cache.common.CacheKey;
|
|
||||||
import com.facebook.cache.common.SimpleCacheKey;
|
|
||||||
import com.facebook.cache.disk.DiskStorage;
|
|
||||||
import com.facebook.common.internal.ByteStreams;
|
|
||||||
import com.facebook.common.internal.Preconditions;
|
|
||||||
import com.facebook.common.internal.Predicate;
|
|
||||||
import com.facebook.common.memory.PooledByteBuffer;
|
|
||||||
import com.facebook.common.memory.PooledByteBufferInputStream;
|
|
||||||
import com.facebook.common.memory.manager.DebugMemoryManager;
|
|
||||||
import com.facebook.common.memory.manager.NoOpDebugMemoryManager;
|
|
||||||
import com.facebook.common.references.CloseableReference;
|
|
||||||
import com.facebook.common.references.SharedReference;
|
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
|
||||||
import com.facebook.drawee.backends.pipeline.info.ImageLoadStatus;
|
|
||||||
import com.facebook.drawee.backends.pipeline.info.ImageOriginUtils;
|
|
||||||
import com.facebook.drawee.backends.pipeline.info.ImagePerfData;
|
|
||||||
import com.facebook.drawee.backends.pipeline.info.ImagePerfDataListener;
|
|
||||||
import com.facebook.flipper.core.FlipperArray;
|
|
||||||
import com.facebook.flipper.core.FlipperConnection;
|
|
||||||
import com.facebook.flipper.core.FlipperObject;
|
|
||||||
import com.facebook.flipper.core.FlipperReceiver;
|
|
||||||
import com.facebook.flipper.core.FlipperResponder;
|
|
||||||
import com.facebook.flipper.perflogger.FlipperPerfLogger;
|
|
||||||
import com.facebook.flipper.perflogger.NoOpFlipperPerfLogger;
|
|
||||||
import com.facebook.flipper.plugins.common.BufferingFlipperPlugin;
|
|
||||||
import com.facebook.flipper.plugins.fresco.objecthelper.FlipperObjectHelper;
|
|
||||||
import com.facebook.imagepipeline.bitmaps.PlatformBitmapFactory;
|
|
||||||
import com.facebook.imagepipeline.cache.CountingMemoryCacheInspector;
|
|
||||||
import com.facebook.imagepipeline.cache.CountingMemoryCacheInspector.DumpInfoEntry;
|
|
||||||
import com.facebook.imagepipeline.core.ImagePipelineFactory;
|
|
||||||
import com.facebook.imagepipeline.debug.CloseableReferenceLeakTracker;
|
|
||||||
import com.facebook.imagepipeline.debug.DebugImageTracker;
|
|
||||||
import com.facebook.imagepipeline.debug.FlipperImageTracker;
|
|
||||||
import com.facebook.imagepipeline.image.CloseableBitmap;
|
|
||||||
import com.facebook.imagepipeline.image.CloseableImage;
|
|
||||||
import com.facebook.imagepipeline.image.EncodedImage;
|
|
||||||
import com.facebook.imageutils.BitmapUtil;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows Sonar to display the contents of Fresco's caches. This is useful for developers to debug
|
|
||||||
* what images are being held in cache as they navigate through their app.
|
|
||||||
*/
|
|
||||||
public class FrescoFlipperPlugin extends BufferingFlipperPlugin
|
|
||||||
implements ImagePerfDataListener, CloseableReferenceLeakTracker.Listener {
|
|
||||||
|
|
||||||
private static final String FRESCO_EVENT = "events";
|
|
||||||
private static final String FRESCO_DEBUGOVERLAY_EVENT = "debug_overlay_event";
|
|
||||||
private static final String FRESCO_CLOSEABLE_REFERENCE_LEAK_EVENT =
|
|
||||||
"closeable_reference_leak_event";
|
|
||||||
|
|
||||||
private static final int BITMAP_PREVIEW_WIDTH = 150;
|
|
||||||
private static final int BITMAP_PREVIEW_HEIGHT = 150;
|
|
||||||
private static final int BITMAP_SCALING_THRESHOLD_WIDTH = 200;
|
|
||||||
private static final int BITMAP_SCALING_THRESHOLD_HEIGHT = 200;
|
|
||||||
|
|
||||||
/** Helper for clearing cache. */
|
|
||||||
private static final Predicate<CacheKey> ALWAYS_TRUE_PREDICATE =
|
|
||||||
new Predicate<CacheKey>() {
|
|
||||||
@Override
|
|
||||||
public boolean apply(CacheKey cacheKey) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final FlipperImageTracker mFlipperImageTracker;
|
|
||||||
private final PlatformBitmapFactory mPlatformBitmapFactory;
|
|
||||||
@Nullable private final FlipperObjectHelper mSonarObjectHelper;
|
|
||||||
private final DebugMemoryManager mMemoryManager;
|
|
||||||
private final FlipperPerfLogger mPerfLogger;
|
|
||||||
@Nullable private final FrescoFlipperDebugPrefHelper mDebugPrefHelper;
|
|
||||||
private final List<FlipperObject> mEvents = new ArrayList<>();
|
|
||||||
|
|
||||||
public FrescoFlipperPlugin(
|
|
||||||
DebugImageTracker imageTracker,
|
|
||||||
PlatformBitmapFactory bitmapFactory,
|
|
||||||
@Nullable FlipperObjectHelper flipperObjectHelper,
|
|
||||||
DebugMemoryManager memoryManager,
|
|
||||||
FlipperPerfLogger perfLogger,
|
|
||||||
@Nullable FrescoFlipperDebugPrefHelper debugPrefHelper,
|
|
||||||
@Nullable CloseableReferenceLeakTracker closeableReferenceLeakTracker) {
|
|
||||||
mFlipperImageTracker =
|
|
||||||
imageTracker instanceof FlipperImageTracker
|
|
||||||
? (FlipperImageTracker) imageTracker
|
|
||||||
: new FlipperImageTracker();
|
|
||||||
mPlatformBitmapFactory = bitmapFactory;
|
|
||||||
mSonarObjectHelper = flipperObjectHelper;
|
|
||||||
mMemoryManager = memoryManager;
|
|
||||||
mPerfLogger = perfLogger;
|
|
||||||
mDebugPrefHelper = debugPrefHelper;
|
|
||||||
|
|
||||||
if (closeableReferenceLeakTracker != null) {
|
|
||||||
closeableReferenceLeakTracker.setListener(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public FrescoFlipperPlugin() {
|
|
||||||
this(
|
|
||||||
new FlipperImageTracker(),
|
|
||||||
Fresco.getImagePipelineFactory().getPlatformBitmapFactory(),
|
|
||||||
null,
|
|
||||||
new NoOpDebugMemoryManager(),
|
|
||||||
new NoOpFlipperPerfLogger(),
|
|
||||||
null,
|
|
||||||
null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FlipperImageTracker getFlipperImageTracker() {
|
|
||||||
return mFlipperImageTracker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return "Fresco";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConnect(FlipperConnection connection) {
|
|
||||||
super.onConnect(connection);
|
|
||||||
connection.receive(
|
|
||||||
"getAllImageEventsInfo",
|
|
||||||
new FlipperReceiver() {
|
|
||||||
@Override
|
|
||||||
public void onReceive(FlipperObject params, FlipperResponder responder) throws Exception {
|
|
||||||
if (!ensureFrescoInitialized()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FlipperArray.Builder arrayBuilder = new FlipperArray.Builder();
|
|
||||||
for (FlipperObject obj : mEvents) {
|
|
||||||
arrayBuilder.put(obj);
|
|
||||||
}
|
|
||||||
mEvents.clear();
|
|
||||||
|
|
||||||
FlipperObject object =
|
|
||||||
new FlipperObject.Builder().put("events", arrayBuilder.build()).build();
|
|
||||||
responder.success(object);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
connection.receive(
|
|
||||||
"listImages",
|
|
||||||
new FlipperReceiver() {
|
|
||||||
@Override
|
|
||||||
public void onReceive(FlipperObject params, FlipperResponder responder) throws Exception {
|
|
||||||
if (!ensureFrescoInitialized()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mPerfLogger.startMarker("Sonar.Fresco.listImages");
|
|
||||||
final boolean showDiskImages = params.getBoolean("showDiskImages");
|
|
||||||
final ImagePipelineFactory imagePipelineFactory = Fresco.getImagePipelineFactory();
|
|
||||||
|
|
||||||
final CountingMemoryCacheInspector.DumpInfo bitmapMemoryCache =
|
|
||||||
new CountingMemoryCacheInspector<>(
|
|
||||||
imagePipelineFactory.getBitmapCountingMemoryCache())
|
|
||||||
.dumpCacheContent();
|
|
||||||
final CountingMemoryCacheInspector.DumpInfo encodedMemoryCache =
|
|
||||||
new CountingMemoryCacheInspector<>(
|
|
||||||
imagePipelineFactory.getEncodedCountingMemoryCache())
|
|
||||||
.dumpCacheContent();
|
|
||||||
|
|
||||||
try {
|
|
||||||
responder.success(
|
|
||||||
getImageList(bitmapMemoryCache, encodedMemoryCache, showDiskImages));
|
|
||||||
mPerfLogger.endMarker("Sonar.Fresco.listImages");
|
|
||||||
} finally {
|
|
||||||
bitmapMemoryCache.release();
|
|
||||||
encodedMemoryCache.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
connection.receive(
|
|
||||||
"getImage",
|
|
||||||
new FlipperReceiver() {
|
|
||||||
@Override
|
|
||||||
public void onReceive(FlipperObject params, final FlipperResponder responder)
|
|
||||||
throws Exception {
|
|
||||||
if (!ensureFrescoInitialized()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mPerfLogger.startMarker("Sonar.Fresco.getImage");
|
|
||||||
final String imageId = params.getString("imageId");
|
|
||||||
final CacheKey cacheKey = mFlipperImageTracker.getCacheKey(imageId);
|
|
||||||
if (cacheKey == null) {
|
|
||||||
respondError(responder, "ImageId " + imageId + " was evicted from cache");
|
|
||||||
mPerfLogger.cancelMarker("Sonar.Fresco.getImage");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final ImagePipelineFactory imagePipelineFactory = Fresco.getImagePipelineFactory();
|
|
||||||
|
|
||||||
// try to load from bitmap cache
|
|
||||||
@Nullable
|
|
||||||
CloseableImage closeableImage =
|
|
||||||
imagePipelineFactory.getBitmapCountingMemoryCache().inspect(cacheKey);
|
|
||||||
if (closeableImage instanceof CloseableBitmap) {
|
|
||||||
@Nullable Bitmap bitmap = ((CloseableBitmap) closeableImage).getUnderlyingBitmap();
|
|
||||||
if (bitmap != null) {
|
|
||||||
loadFromBitmapCache(bitmap, imageId, cacheKey, responder);
|
|
||||||
mPerfLogger.endMarker("Sonar.Fresco.getImage");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// try to load from encoded cache
|
|
||||||
PooledByteBuffer encoded =
|
|
||||||
imagePipelineFactory.getEncodedCountingMemoryCache().inspect(cacheKey);
|
|
||||||
if (encoded != null) {
|
|
||||||
loadFromEncodedCache(encoded, imageId, cacheKey, responder);
|
|
||||||
mPerfLogger.endMarker("Sonar.Fresco.getImage");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// try to load from disk
|
|
||||||
loadFromDisk(imageId, cacheKey, responder);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadFromBitmapCache(
|
|
||||||
final Bitmap bitmap,
|
|
||||||
final String imageId,
|
|
||||||
final CacheKey cacheKey,
|
|
||||||
final FlipperResponder responder) {
|
|
||||||
String encodedBitmap = bitmapToBase64Preview(bitmap, mPlatformBitmapFactory);
|
|
||||||
responder.success(
|
|
||||||
getImageData(
|
|
||||||
imageId,
|
|
||||||
mFlipperImageTracker.getUriString(cacheKey),
|
|
||||||
bitmap.getWidth(),
|
|
||||||
bitmap.getHeight(),
|
|
||||||
BitmapUtil.getSizeInBytes(bitmap),
|
|
||||||
encodedBitmap));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadFromEncodedCache(
|
|
||||||
final PooledByteBuffer encoded,
|
|
||||||
final String imageId,
|
|
||||||
final CacheKey cacheKey,
|
|
||||||
final FlipperResponder responder)
|
|
||||||
throws Exception {
|
|
||||||
byte[] encodedArray = ByteStreams.toByteArray(new PooledByteBufferInputStream(encoded));
|
|
||||||
Pair<Integer, Integer> dimensions = BitmapUtil.decodeDimensions(encodedArray);
|
|
||||||
if (dimensions == null) {
|
|
||||||
respondError(responder, "can not get dimensions withId=" + imageId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
responder.success(
|
|
||||||
getImageData(
|
|
||||||
imageId,
|
|
||||||
mFlipperImageTracker.getUriString(cacheKey),
|
|
||||||
dimensions.first,
|
|
||||||
dimensions.second,
|
|
||||||
encodedArray.length,
|
|
||||||
dataFromEncodedArray(encodedArray)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadFromDisk(
|
|
||||||
final String imageId, final CacheKey cacheKey, final FlipperResponder responder) {
|
|
||||||
Task<EncodedImage> t =
|
|
||||||
Fresco.getImagePipelineFactory()
|
|
||||||
.getMainBufferedDiskCache()
|
|
||||||
.get(cacheKey, new AtomicBoolean(false));
|
|
||||||
|
|
||||||
t.continueWith(
|
|
||||||
new Continuation<EncodedImage, Void>() {
|
|
||||||
public Void then(Task<EncodedImage> task) throws Exception {
|
|
||||||
if (task.isCancelled() || task.isFaulted()) {
|
|
||||||
respondError(responder, "no bitmap withId=" + imageId);
|
|
||||||
mPerfLogger.cancelMarker("Sonar.Fresco.getImage");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Preconditions.checkNotNull(task);
|
|
||||||
final EncodedImage image = task.getResult();
|
|
||||||
try {
|
|
||||||
InputStream stream = Preconditions.checkNotNull(image.getInputStream());
|
|
||||||
byte[] encodedArray = ByteStreams.toByteArray(stream);
|
|
||||||
|
|
||||||
responder.success(
|
|
||||||
getImageData(
|
|
||||||
imageId,
|
|
||||||
Preconditions.checkNotNull(
|
|
||||||
mFlipperImageTracker.getLocalPath(cacheKey)),
|
|
||||||
image.getWidth(),
|
|
||||||
image.getHeight(),
|
|
||||||
encodedArray.length,
|
|
||||||
dataFromEncodedArray(encodedArray)));
|
|
||||||
} finally {
|
|
||||||
EncodedImage.closeSafely(image);
|
|
||||||
}
|
|
||||||
mPerfLogger.endMarker("Sonar.Fresco.getImage");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
connection.receive(
|
|
||||||
"clear",
|
|
||||||
new FlipperReceiver() {
|
|
||||||
@Override
|
|
||||||
public void onReceive(FlipperObject params, FlipperResponder responder) {
|
|
||||||
if (!ensureFrescoInitialized()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mPerfLogger.startMarker("Sonar.Fresco.clear");
|
|
||||||
final String type = params.getString("type");
|
|
||||||
switch (type) {
|
|
||||||
case "memory":
|
|
||||||
final ImagePipelineFactory imagePipelineFactory = Fresco.getImagePipelineFactory();
|
|
||||||
imagePipelineFactory.getBitmapMemoryCache().removeAll(ALWAYS_TRUE_PREDICATE);
|
|
||||||
break;
|
|
||||||
case "disk":
|
|
||||||
Fresco.getImagePipeline().clearDiskCaches();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mPerfLogger.endMarker("Sonar.Fresco.clear");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
connection.receive(
|
|
||||||
"trimMemory",
|
|
||||||
new FlipperReceiver() {
|
|
||||||
@Override
|
|
||||||
public void onReceive(FlipperObject params, FlipperResponder responder) throws Exception {
|
|
||||||
if (!ensureFrescoInitialized()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mMemoryManager != null) {
|
|
||||||
mMemoryManager.trimMemory(
|
|
||||||
DebugMemoryManager.ON_SYSTEM_LOW_MEMORY_WHILE_APP_IN_FOREGROUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
connection.receive(
|
|
||||||
"enableDebugOverlay",
|
|
||||||
new FlipperReceiver() {
|
|
||||||
@Override
|
|
||||||
public void onReceive(FlipperObject params, FlipperResponder responder) throws Exception {
|
|
||||||
if (!ensureFrescoInitialized()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final boolean enabled = params.getBoolean("enabled");
|
|
||||||
if (mDebugPrefHelper != null) {
|
|
||||||
mDebugPrefHelper.setDebugOverlayEnabled(enabled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (mDebugPrefHelper != null) {
|
|
||||||
mDebugPrefHelper.setDebugOverlayEnabledListener(
|
|
||||||
new FrescoFlipperDebugPrefHelper.Listener() {
|
|
||||||
@Override
|
|
||||||
public void onEnabledStatusChanged(boolean enabled) {
|
|
||||||
sendDebugOverlayEnabledEvent(enabled);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
sendDebugOverlayEnabledEvent(mDebugPrefHelper.isDebugOverlayEnabled());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String dataFromEncodedArray(byte[] encodedArray) {
|
|
||||||
return "data:image/jpeg;base64," + Base64.encodeToString(encodedArray, Base64.DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
private FlipperObject getImageList(
|
|
||||||
final CountingMemoryCacheInspector.DumpInfo bitmapMemoryCache,
|
|
||||||
final CountingMemoryCacheInspector.DumpInfo encodedMemoryCache,
|
|
||||||
final boolean showDiskImages)
|
|
||||||
throws IOException {
|
|
||||||
FlipperArray.Builder levelsBuilder =
|
|
||||||
new FlipperArray.Builder()
|
|
||||||
// bitmap
|
|
||||||
.put(getUsedStats("On screen bitmaps", bitmapMemoryCache))
|
|
||||||
.put(getCachedStats("Bitmap memory cache", bitmapMemoryCache))
|
|
||||||
// encoded
|
|
||||||
.put(getUsedStats("Used encoded images", encodedMemoryCache))
|
|
||||||
.put(getCachedStats("Cached encoded images", encodedMemoryCache));
|
|
||||||
if (showDiskImages) {
|
|
||||||
levelsBuilder.put(
|
|
||||||
getDiskStats(
|
|
||||||
"Disk images",
|
|
||||||
Fresco.getImagePipelineFactory().getMainFileCache().getDumpInfo().entries));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new FlipperObject.Builder().put("levels", levelsBuilder.build()).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private FlipperObject getUsedStats(
|
|
||||||
final String cacheType, final CountingMemoryCacheInspector.DumpInfo memoryCache) {
|
|
||||||
return new FlipperObject.Builder()
|
|
||||||
.put("cacheType", cacheType)
|
|
||||||
.put("sizeBytes", memoryCache.size - memoryCache.lruSize)
|
|
||||||
.put("imageIds", buildImageIdList(memoryCache.sharedEntries))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private FlipperObject getCachedStats(
|
|
||||||
final String cacheType, final CountingMemoryCacheInspector.DumpInfo memoryCache) {
|
|
||||||
return new FlipperObject.Builder()
|
|
||||||
.put("cacheType", cacheType)
|
|
||||||
.put("clearKey", "memory")
|
|
||||||
.put("sizeBytes", memoryCache.size)
|
|
||||||
.put("maxSizeBytes", memoryCache.maxSize)
|
|
||||||
.put("imageIds", buildImageIdList(memoryCache.lruEntries))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private FlipperObject getDiskStats(
|
|
||||||
final String cacheType, List<DiskStorage.DiskDumpInfoEntry> diskEntries) {
|
|
||||||
return new FlipperObject.Builder()
|
|
||||||
.put("cacheType", cacheType)
|
|
||||||
.put("clearKey", "disk")
|
|
||||||
.put("sizeBytes", Fresco.getImagePipelineFactory().getMainFileCache().getSize())
|
|
||||||
.put("imageIds", buildImageIdListDisk(diskEntries))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static FlipperObject getImageData(
|
|
||||||
String imageID, String uriString, int width, int height, int sizeBytes, String data) {
|
|
||||||
return new FlipperObject.Builder()
|
|
||||||
.put("imageId", imageID)
|
|
||||||
.put("uri", uriString)
|
|
||||||
.put("width", width)
|
|
||||||
.put("height", height)
|
|
||||||
.put("sizeBytes", sizeBytes)
|
|
||||||
.put("data", data)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean ensureFrescoInitialized() {
|
|
||||||
mPerfLogger.startMarker("Sonar.Fresco.ensureFrescoInitialized");
|
|
||||||
try {
|
|
||||||
Fresco.getImagePipelineFactory();
|
|
||||||
return true;
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
return false;
|
|
||||||
} finally {
|
|
||||||
mPerfLogger.endMarker("Sonar.Fresco.ensureFrescoInitialized");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private FlipperArray buildImageIdList(List<DumpInfoEntry<CacheKey, CloseableImage>> images) {
|
|
||||||
FlipperArray.Builder builder = new FlipperArray.Builder();
|
|
||||||
for (DumpInfoEntry<CacheKey, CloseableImage> entry : images) {
|
|
||||||
final FlipperImageTracker.ImageDebugData imageDebugData =
|
|
||||||
mFlipperImageTracker.getImageDebugData(entry.key);
|
|
||||||
|
|
||||||
if (imageDebugData == null) {
|
|
||||||
builder.put(mFlipperImageTracker.trackImage(entry.key).getUniqueId());
|
|
||||||
} else {
|
|
||||||
builder.put(imageDebugData.getUniqueId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private FlipperArray buildImageIdListDisk(List<DiskStorage.DiskDumpInfoEntry> diskEntries) {
|
|
||||||
FlipperArray.Builder builder = new FlipperArray.Builder();
|
|
||||||
for (DiskStorage.DiskDumpInfoEntry entry : diskEntries) {
|
|
||||||
final CacheKey entryCacheKey = new SimpleCacheKey(entry.id, true);
|
|
||||||
final FlipperImageTracker.ImageDebugData imageDebugData =
|
|
||||||
mFlipperImageTracker.getImageDebugData(entryCacheKey);
|
|
||||||
|
|
||||||
if (imageDebugData == null) {
|
|
||||||
builder.put(mFlipperImageTracker.trackImage(entry.path, entryCacheKey).getUniqueId());
|
|
||||||
} else {
|
|
||||||
builder.put(imageDebugData.getUniqueId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String bitmapToBase64Preview(Bitmap bitmap, PlatformBitmapFactory bitmapFactory) {
|
|
||||||
if (bitmap.getWidth() < BITMAP_SCALING_THRESHOLD_WIDTH
|
|
||||||
&& bitmap.getHeight() < BITMAP_SCALING_THRESHOLD_HEIGHT) {
|
|
||||||
return bitmapToBase64WithoutScaling(bitmap);
|
|
||||||
}
|
|
||||||
mPerfLogger.startMarker("Sonar.Fresco.bitmap2base64-resize");
|
|
||||||
|
|
||||||
// TODO (t19034797): properly load images
|
|
||||||
CloseableReference<Bitmap> scaledBitmapReference = null;
|
|
||||||
try {
|
|
||||||
float previewAspectRatio = BITMAP_PREVIEW_WIDTH / BITMAP_PREVIEW_HEIGHT;
|
|
||||||
float imageAspectRatio = bitmap.getWidth() / bitmap.getHeight();
|
|
||||||
|
|
||||||
int scaledWidth;
|
|
||||||
int scaledHeight;
|
|
||||||
if (previewAspectRatio > imageAspectRatio) {
|
|
||||||
scaledWidth = bitmap.getWidth() * BITMAP_PREVIEW_HEIGHT / bitmap.getHeight();
|
|
||||||
scaledHeight = BITMAP_PREVIEW_HEIGHT;
|
|
||||||
} else {
|
|
||||||
scaledWidth = BITMAP_PREVIEW_WIDTH;
|
|
||||||
scaledHeight = bitmap.getHeight() * BITMAP_PREVIEW_WIDTH / bitmap.getWidth();
|
|
||||||
}
|
|
||||||
scaledBitmapReference =
|
|
||||||
bitmapFactory.createScaledBitmap(bitmap, scaledWidth, scaledHeight, false);
|
|
||||||
return bitmapToBase64WithoutScaling(scaledBitmapReference.get());
|
|
||||||
} finally {
|
|
||||||
CloseableReference.closeSafely(scaledBitmapReference);
|
|
||||||
mPerfLogger.endMarker("Sonar.Fresco.bitmap2base64-resize");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String bitmapToBase64WithoutScaling(Bitmap bitmap) {
|
|
||||||
mPerfLogger.startMarker("Sonar.Fresco.bitmap2base64-orig");
|
|
||||||
ByteArrayOutputStream byteArrayOutputStream = null;
|
|
||||||
try {
|
|
||||||
byteArrayOutputStream = new ByteArrayOutputStream();
|
|
||||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
|
|
||||||
|
|
||||||
return "data:image/png;base64,"
|
|
||||||
+ Base64.encodeToString(byteArrayOutputStream.toByteArray(), Base64.DEFAULT);
|
|
||||||
} finally {
|
|
||||||
if (byteArrayOutputStream != null) {
|
|
||||||
try {
|
|
||||||
byteArrayOutputStream.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mPerfLogger.endMarker("Sonar.Fresco.bitmap2base64-orig");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onImageLoadStatusUpdated(
|
|
||||||
ImagePerfData imagePerfData, @ImageLoadStatus int imageLoadStatus) {
|
|
||||||
if (imageLoadStatus != ImageLoadStatus.SUCCESS) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String requestId = imagePerfData.getRequestId();
|
|
||||||
if (requestId == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FlipperImageTracker.ImageDebugData data =
|
|
||||||
mFlipperImageTracker.getDebugDataForRequestId(requestId);
|
|
||||||
if (data == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FlipperArray.Builder imageIdsBuilder = new FlipperArray.Builder();
|
|
||||||
Set<CacheKey> cks = data.getCacheKeys();
|
|
||||||
if (cks != null) {
|
|
||||||
for (CacheKey ck : cks) {
|
|
||||||
FlipperImageTracker.ImageDebugData d = mFlipperImageTracker.getImageDebugData(ck);
|
|
||||||
if (d != null) {
|
|
||||||
imageIdsBuilder.put(d.getUniqueId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
imageIdsBuilder.put(data.getUniqueId());
|
|
||||||
}
|
|
||||||
|
|
||||||
FlipperArray attribution;
|
|
||||||
Object callerContext = imagePerfData.getCallerContext();
|
|
||||||
if (callerContext == null) {
|
|
||||||
attribution = new FlipperArray.Builder().put("unknown").build();
|
|
||||||
} else if (mSonarObjectHelper == null) {
|
|
||||||
attribution = new FlipperArray.Builder().put(callerContext.toString()).build();
|
|
||||||
} else {
|
|
||||||
attribution = mSonarObjectHelper.fromCallerContext(callerContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
FlipperObject.Builder response =
|
|
||||||
new FlipperObject.Builder()
|
|
||||||
.put("imageIds", imageIdsBuilder.build())
|
|
||||||
.put("attribution", attribution)
|
|
||||||
.put("startTime", imagePerfData.getControllerSubmitTimeMs())
|
|
||||||
.put("endTime", imagePerfData.getControllerFinalImageSetTimeMs())
|
|
||||||
.put("source", ImageOriginUtils.toString(imagePerfData.getImageOrigin()));
|
|
||||||
|
|
||||||
if (!imagePerfData.isPrefetch()) {
|
|
||||||
response.put(
|
|
||||||
"viewport",
|
|
||||||
new FlipperObject.Builder()
|
|
||||||
// TODO (t31947746): scan times
|
|
||||||
.put("width", imagePerfData.getOnScreenWidthPx())
|
|
||||||
.put("height", imagePerfData.getOnScreenHeightPx())
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
FlipperObject responseObject = response.build();
|
|
||||||
mEvents.add(responseObject);
|
|
||||||
send(FRESCO_EVENT, responseObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onImageVisibilityUpdated(ImagePerfData imagePerfData, int visibilityState) {
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendDebugOverlayEnabledEvent(final boolean enabled) {
|
|
||||||
final FlipperObject.Builder builder = new FlipperObject.Builder().put("enabled", enabled);
|
|
||||||
send(FRESCO_DEBUGOVERLAY_EVENT, builder.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void respondError(FlipperResponder responder, String errorReason) {
|
|
||||||
responder.error(new FlipperObject.Builder().put("reason", errorReason).build());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCloseableReferenceLeak(
|
|
||||||
SharedReference<Object> reference, @Nullable Throwable stacktrace) {
|
|
||||||
Object object = reference.get();
|
|
||||||
Preconditions.checkNotNull(object);
|
|
||||||
final FlipperObject.Builder builder =
|
|
||||||
new FlipperObject.Builder()
|
|
||||||
.put("identityHashCode", System.identityHashCode(reference))
|
|
||||||
.put("className", object.getClass().getName());
|
|
||||||
if (stacktrace != null) {
|
|
||||||
builder.put("stacktrace", getStackTraceString(stacktrace));
|
|
||||||
}
|
|
||||||
send(FRESCO_CLOSEABLE_REFERENCE_LEAK_EVENT, builder.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getStackTraceString(Throwable tr) {
|
|
||||||
StringWriter sw = new StringWriter();
|
|
||||||
PrintWriter pw = new PrintWriter(sw);
|
|
||||||
tr.printStackTrace(pw);
|
|
||||||
return sw.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.facebook.flipper.plugins.fresco;
|
|
||||||
|
|
||||||
import com.facebook.imagepipeline.debug.DebugImageTracker;
|
|
||||||
import com.facebook.imagepipeline.listener.BaseRequestListener;
|
|
||||||
import com.facebook.imagepipeline.request.ImageRequest;
|
|
||||||
|
|
||||||
/** Fresco image {@link RequestListener} that logs events for Sonar. */
|
|
||||||
public class FrescoFlipperRequestListener extends BaseRequestListener {
|
|
||||||
|
|
||||||
private final DebugImageTracker mDebugImageTracker;
|
|
||||||
|
|
||||||
public FrescoFlipperRequestListener(DebugImageTracker debugImageTracker) {
|
|
||||||
mDebugImageTracker = debugImageTracker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRequestStart(
|
|
||||||
ImageRequest request, Object callerContext, String requestId, boolean isPrefetch) {
|
|
||||||
mDebugImageTracker.trackImageRequest(request, requestId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,216 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.facebook.flipper.plugins.fresco.objecthelper;
|
|
||||||
|
|
||||||
import static com.facebook.flipper.plugins.inspector.InspectorValue.Type.Color;
|
|
||||||
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import com.facebook.drawee.backends.pipeline.info.ImageOriginUtils;
|
|
||||||
import com.facebook.drawee.backends.pipeline.info.ImagePerfData;
|
|
||||||
import com.facebook.drawee.generic.RoundingParams;
|
|
||||||
import com.facebook.flipper.core.FlipperArray;
|
|
||||||
import com.facebook.flipper.core.FlipperObject;
|
|
||||||
import com.facebook.flipper.plugins.inspector.InspectorValue;
|
|
||||||
import com.facebook.imagepipeline.common.ImageDecodeOptions;
|
|
||||||
import com.facebook.imagepipeline.common.ResizeOptions;
|
|
||||||
import com.facebook.imagepipeline.common.RotationOptions;
|
|
||||||
import com.facebook.imagepipeline.debug.FlipperImageTracker;
|
|
||||||
import com.facebook.imagepipeline.image.ImageInfo;
|
|
||||||
import com.facebook.imagepipeline.image.QualityInfo;
|
|
||||||
import com.facebook.imagepipeline.request.ImageRequest;
|
|
||||||
import java.util.Map;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
/** Serialization helper to create {@link FlipperObject}s. */
|
|
||||||
public abstract class FlipperObjectHelper {
|
|
||||||
|
|
||||||
public FlipperObject keyValuePair(String key, @Nullable String value) {
|
|
||||||
return new FlipperObject.Builder().put(key, value).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public FlipperObject toFlipperObject(@Nullable Map<String, String> stringMap) {
|
|
||||||
if (stringMap == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
FlipperObject.Builder optionsJson = new FlipperObject.Builder();
|
|
||||||
for (Map.Entry<String, String> entry : stringMap.entrySet()) {
|
|
||||||
optionsJson.put(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
return optionsJson.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public FlipperObject toFlipperObject(@Nullable ImageRequest imageRequest) {
|
|
||||||
if (imageRequest == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
FlipperObject.Builder optionsJson = new FlipperObject.Builder();
|
|
||||||
return addImageRequestProperties(optionsJson, imageRequest).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public FlipperObject toFlipperObject(
|
|
||||||
@Nullable FlipperImageTracker.ImageDebugData imageDebugData) {
|
|
||||||
if (imageDebugData == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
FlipperObject.Builder optionsJson = new FlipperObject.Builder();
|
|
||||||
optionsJson.put("imageId", imageDebugData.getUniqueId());
|
|
||||||
optionsJson.put("imageRequest", toFlipperObject(imageDebugData.getImageRequest()));
|
|
||||||
optionsJson.put(
|
|
||||||
"requestId",
|
|
||||||
imageDebugData.getRequestIds() != null
|
|
||||||
? TextUtils.join(", ", imageDebugData.getRequestIds())
|
|
||||||
: "");
|
|
||||||
optionsJson.put("imagePerfData", toFlipperObject(imageDebugData.getImagePerfData()));
|
|
||||||
return optionsJson.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public FlipperObject toFlipperObject(@Nullable ImageDecodeOptions options) {
|
|
||||||
if (options == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
FlipperObject.Builder optionsJson = new FlipperObject.Builder();
|
|
||||||
optionsJson.put("minDecodeIntervalMs", options.minDecodeIntervalMs);
|
|
||||||
optionsJson.put("decodePreviewFrame", options.decodePreviewFrame);
|
|
||||||
optionsJson.put("useLastFrameForPreview", options.useLastFrameForPreview);
|
|
||||||
optionsJson.put("decodeAllFrames", options.decodeAllFrames);
|
|
||||||
optionsJson.put("forceStaticImage", options.forceStaticImage);
|
|
||||||
optionsJson.put("bitmapConfig", options.bitmapConfig.name());
|
|
||||||
optionsJson.put(
|
|
||||||
"customImageDecoder",
|
|
||||||
options.customImageDecoder == null ? "" : options.customImageDecoder.toString());
|
|
||||||
return optionsJson.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public FlipperObject toFlipperObject(@Nullable ResizeOptions resizeOptions) {
|
|
||||||
if (resizeOptions == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
FlipperObject.Builder optionsJson = new FlipperObject.Builder();
|
|
||||||
optionsJson.put("width", resizeOptions.width);
|
|
||||||
optionsJson.put("height", resizeOptions.height);
|
|
||||||
optionsJson.put("maxBitmapSize", resizeOptions.maxBitmapSize);
|
|
||||||
optionsJson.put("roundUpFraction", resizeOptions.roundUpFraction);
|
|
||||||
return optionsJson.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public FlipperObject toFlipperObject(@Nullable RotationOptions rotationOptions) {
|
|
||||||
if (rotationOptions == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
FlipperObject.Builder optionsJson = new FlipperObject.Builder();
|
|
||||||
optionsJson.put("rotationEnabled", rotationOptions.rotationEnabled());
|
|
||||||
optionsJson.put("canDeferUntilRendered", rotationOptions.canDeferUntilRendered());
|
|
||||||
optionsJson.put("useImageMetadata", rotationOptions.useImageMetadata());
|
|
||||||
if (!rotationOptions.useImageMetadata()) {
|
|
||||||
optionsJson.put("forcedAngle", rotationOptions.getForcedAngle());
|
|
||||||
}
|
|
||||||
return optionsJson.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public FlipperObject toFlipperObject(@Nullable RoundingParams roundingParams) {
|
|
||||||
if (roundingParams == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
FlipperObject.Builder optionsJson = new FlipperObject.Builder();
|
|
||||||
optionsJson.put("borderWidth", roundingParams.getBorderWidth());
|
|
||||||
optionsJson.put("cornersRadii", toSonarArray(roundingParams.getCornersRadii()));
|
|
||||||
optionsJson.put("padding", roundingParams.getPadding());
|
|
||||||
optionsJson.put("roundAsCircle", roundingParams.getRoundAsCircle());
|
|
||||||
optionsJson.put("roundingMethod", roundingParams.getRoundingMethod());
|
|
||||||
optionsJson.put(
|
|
||||||
"borderColor", InspectorValue.immutable(Color, roundingParams.getBorderColor()));
|
|
||||||
optionsJson.put(
|
|
||||||
"overlayColor", InspectorValue.immutable(Color, roundingParams.getOverlayColor()));
|
|
||||||
return optionsJson.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public FlipperObject toFlipperObject(@Nullable ImagePerfData imagePerfData) {
|
|
||||||
if (imagePerfData == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
FlipperObject.Builder objectJson = new FlipperObject.Builder();
|
|
||||||
objectJson.put("requestId", imagePerfData.getRequestId());
|
|
||||||
objectJson.put("controllerSubmitTimeMs", imagePerfData.getControllerSubmitTimeMs());
|
|
||||||
objectJson.put("controllerFinalTimeMs", imagePerfData.getControllerFinalImageSetTimeMs());
|
|
||||||
objectJson.put("imageRequestStartTimeMs", imagePerfData.getImageRequestStartTimeMs());
|
|
||||||
objectJson.put("imageRequestEndTimeMs", imagePerfData.getImageRequestEndTimeMs());
|
|
||||||
objectJson.put("imageOrigin", ImageOriginUtils.toString(imagePerfData.getImageOrigin()));
|
|
||||||
objectJson.put("isPrefetch", imagePerfData.isPrefetch());
|
|
||||||
objectJson.put("callerContext", imagePerfData.getCallerContext());
|
|
||||||
objectJson.put("imageRequest", toFlipperObject(imagePerfData.getImageRequest()));
|
|
||||||
objectJson.put("imageInfo", toFlipperObject(imagePerfData.getImageInfo()));
|
|
||||||
return objectJson.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public FlipperObject toFlipperObject(ImageInfo imageInfo) {
|
|
||||||
if (imageInfo == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
FlipperObject.Builder objectJson = new FlipperObject.Builder();
|
|
||||||
objectJson.put("imageWidth", imageInfo.getWidth());
|
|
||||||
objectJson.put("imageHeight", imageInfo.getHeight());
|
|
||||||
objectJson.put("qualityInfo", toFlipperObject(imageInfo.getQualityInfo()));
|
|
||||||
return objectJson.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public FlipperObject toFlipperObject(QualityInfo qualityInfo) {
|
|
||||||
if (qualityInfo == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
FlipperObject.Builder objectJson = new FlipperObject.Builder();
|
|
||||||
objectJson.put("quality", qualityInfo.getQuality());
|
|
||||||
objectJson.put("isGoodEnoughQuality", qualityInfo.isOfGoodEnoughQuality());
|
|
||||||
objectJson.put("isFullQuality", qualityInfo.isOfFullQuality());
|
|
||||||
return objectJson.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public FlipperObject.Builder addImageRequestProperties(
|
|
||||||
FlipperObject.Builder builder, @Nullable ImageRequest request) {
|
|
||||||
if (request == null) {
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
builder
|
|
||||||
.put("sourceUri", request.getSourceUri())
|
|
||||||
.put("preferredWidth", request.getPreferredWidth())
|
|
||||||
.put("preferredHeight", request.getPreferredHeight())
|
|
||||||
.put("cacheChoice", request.getCacheChoice())
|
|
||||||
.put("diskCacheEnabled", request.isDiskCacheEnabled())
|
|
||||||
.put("localThumbnailPreviewsEnabled", request.getLocalThumbnailPreviewsEnabled())
|
|
||||||
.put("lowestPermittedRequestLevel", request.getLowestPermittedRequestLevel())
|
|
||||||
.put("priority", request.getPriority().name())
|
|
||||||
.put("progressiveRenderingEnabled", request.getProgressiveRenderingEnabled())
|
|
||||||
.put("postprocessor", String.valueOf(request.getPostprocessor()))
|
|
||||||
.put("requestListener", String.valueOf(request.getRequestListener()))
|
|
||||||
.put("imageDecodeOptions", toFlipperObject(request.getImageDecodeOptions()))
|
|
||||||
.put("bytesRange", request.getBytesRange())
|
|
||||||
.put("resizeOptions", toFlipperObject(request.getResizeOptions()))
|
|
||||||
.put("rotationOptions", toFlipperObject(request.getRotationOptions()));
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
private FlipperArray toSonarArray(float[] floats) {
|
|
||||||
final FlipperArray.Builder builder = new FlipperArray.Builder();
|
|
||||||
for (float f : floats) {
|
|
||||||
builder.put(f);
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public abstract FlipperArray fromCallerContext(@Nullable Object callerContext);
|
|
||||||
}
|
|
||||||
@@ -38,6 +38,15 @@ android {
|
|||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packagingOptions {
|
||||||
|
pickFirst "**/libcrypto.so"
|
||||||
|
pickFirst "**/libevent-2.1.so"
|
||||||
|
pickFirst "**/libevent_core-2.1.so"
|
||||||
|
pickFirst "**/libevent_extra-2.1.so"
|
||||||
|
pickFirst "**/libflipper.so"
|
||||||
|
pickFirst "**/libssl.so"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -57,6 +66,7 @@ dependencies {
|
|||||||
implementation deps.soloader
|
implementation deps.soloader
|
||||||
implementation deps.okhttp3
|
implementation deps.okhttp3
|
||||||
implementation deps.fresco
|
implementation deps.fresco
|
||||||
|
debugImplementation deps.flipperFrescoPlugin
|
||||||
|
|
||||||
// Integration test
|
// Integration test
|
||||||
androidTestImplementation deps.testCore
|
androidTestImplementation deps.testCore
|
||||||
@@ -69,7 +79,6 @@ dependencies {
|
|||||||
testImplementation deps.junit
|
testImplementation deps.junit
|
||||||
|
|
||||||
debugImplementation project(':android')
|
debugImplementation project(':android')
|
||||||
debugImplementation project(':fresco-plugin')
|
|
||||||
debugImplementation project(':network-plugin')
|
debugImplementation project(':network-plugin')
|
||||||
debugImplementation project(':litho-plugin')
|
debugImplementation project(':litho-plugin')
|
||||||
releaseImplementation project(':noop')
|
releaseImplementation project(':noop')
|
||||||
|
|||||||
@@ -36,6 +36,15 @@ android {
|
|||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "1.8"
|
jvmTarget = "1.8"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packagingOptions {
|
||||||
|
pickFirst "**/libcrypto.so"
|
||||||
|
pickFirst "**/libevent-2.1.so"
|
||||||
|
pickFirst "**/libevent_core-2.1.so"
|
||||||
|
pickFirst "**/libevent_extra-2.1.so"
|
||||||
|
pickFirst "**/libflipper.so"
|
||||||
|
pickFirst "**/libssl.so"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -47,9 +56,9 @@ dependencies {
|
|||||||
// For simplicity, we use Flipper for both debug and release builds here.
|
// For simplicity, we use Flipper for both debug and release builds here.
|
||||||
// Check out the "sample" app to see how to separate your build flavors.
|
// Check out the "sample" app to see how to separate your build flavors.
|
||||||
implementation project(':android')
|
implementation project(':android')
|
||||||
implementation project(':fresco-plugin')
|
|
||||||
implementation project(':network-plugin')
|
implementation project(':network-plugin')
|
||||||
implementation project(':litho-plugin')
|
implementation project(':litho-plugin')
|
||||||
|
implementation deps.flipperFrescoPlugin
|
||||||
implementation deps.soloader
|
implementation deps.soloader
|
||||||
|
|
||||||
// Litho
|
// Litho
|
||||||
|
|||||||
@@ -108,7 +108,8 @@ ext.deps = [
|
|||||||
testCore : 'androidx.test:core:1.4.0',
|
testCore : 'androidx.test:core:1.4.0',
|
||||||
testRules : 'androidx.test:rules:1.5.0',
|
testRules : 'androidx.test:rules:1.5.0',
|
||||||
// Plugin dependencies
|
// Plugin dependencies
|
||||||
|
flipperFrescoPlugin: 'com.facebook.flipper:flipper-fresco-plugin:0.182.0',
|
||||||
frescoFlipper : 'com.facebook.fresco:flipper:2.6.0',
|
frescoFlipper : 'com.facebook.fresco:flipper:2.6.0',
|
||||||
frescoStetho : 'com.facebook.fresco:stetho:2.6.0',
|
frescoStetho : 'com.facebook.fresco:stetho:2.6.0',
|
||||||
fresco : 'com.facebook.fresco:fresco:2.6.0'
|
fresco : 'com.facebook.fresco:fresco:2.6.0',
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -28,9 +28,6 @@ project(':third-party').projectDir = file('android/third-party/')
|
|||||||
project(':noop').projectDir = file('android/no-op/')
|
project(':noop').projectDir = file('android/no-op/')
|
||||||
|
|
||||||
// Plugins
|
// Plugins
|
||||||
include ':fresco-plugin'
|
|
||||||
project(':fresco-plugin').projectDir = file('android/plugins/fresco')
|
|
||||||
|
|
||||||
include ':network-plugin'
|
include ':network-plugin'
|
||||||
project(':network-plugin').projectDir = file('android/plugins/network')
|
project(':network-plugin').projectDir = file('android/plugins/network')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user