Disable mass APNG animation on low-memory devices.

fork-5.53.8
Greyson Parrelli 2021-01-24 16:37:32 -05:00
rodzic acbc17c909
commit 92b586c061
12 zmienionych plików z 125 dodań i 30 usunięć

Wyświetl plik

@ -20,7 +20,11 @@ public class ApngBufferCacheDecoder implements ResourceDecoder<ByteBuffer, APNGD
@Override @Override
public boolean handles(@NonNull ByteBuffer source, @NonNull Options options) { public boolean handles(@NonNull ByteBuffer source, @NonNull Options options) {
return APNGParser.isAPNG(new ByteBufferReader(source)); if (options.get(ApngOptions.ANIMATE)) {
return APNGParser.isAPNG(new ByteBufferReader(source));
} else {
return false;
}
} }
@Override @Override

Wyświetl plik

@ -0,0 +1,20 @@
package org.thoughtcrime.securesms.glide.cache;
import com.bumptech.glide.load.Option;
import org.signal.core.util.Conversions;
/**
* Holds options that can be used to alter how APNGs are decoded in Glide.
*/
public final class ApngOptions {
private static final String KEY = "org.signal.skip_apng";
public static Option<Boolean> ANIMATE = Option.disk(KEY, true, (keyBytes, value, messageDigest) -> {
messageDigest.update(keyBytes);
messageDigest.update(Conversions.intToByteArray(value ? 1 : 0));
});
private ApngOptions() {}
}

Wyświetl plik

@ -26,7 +26,11 @@ public class ApngStreamCacheDecoder implements ResourceDecoder<InputStream, APNG
@Override @Override
public boolean handles(@NonNull InputStream source, @NonNull Options options) { public boolean handles(@NonNull InputStream source, @NonNull Options options) {
return APNGParser.isAPNG(new StreamReader(source)); if (options.get(ApngOptions.ANIMATE)) {
return APNGParser.isAPNG(new StreamReader(source));
} else {
return false;
}
} }
@Override @Override

Wyświetl plik

@ -14,6 +14,7 @@ import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.model.StickerRecord; import org.thoughtcrime.securesms.database.model.StickerRecord;
import org.thoughtcrime.securesms.glide.cache.ApngOptions;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
import org.thoughtcrime.securesms.mms.GlideRequests; import org.thoughtcrime.securesms.mms.GlideRequests;
@ -29,13 +30,15 @@ final class StickerKeyboardPageAdapter extends RecyclerView.Adapter<StickerKeybo
private final GlideRequests glideRequests; private final GlideRequests glideRequests;
private final EventListener eventListener; private final EventListener eventListener;
private final List<StickerRecord> stickers; private final List<StickerRecord> stickers;
private final boolean allowApngAnimation;
private int stickerSize; private int stickerSize;
StickerKeyboardPageAdapter(@NonNull GlideRequests glideRequests, @NonNull EventListener eventListener) { StickerKeyboardPageAdapter(@NonNull GlideRequests glideRequests, @NonNull EventListener eventListener, boolean allowApngAnimation) {
this.glideRequests = glideRequests; this.glideRequests = glideRequests;
this.eventListener = eventListener; this.eventListener = eventListener;
this.stickers = new ArrayList<>(); this.allowApngAnimation = allowApngAnimation;
this.stickers = new ArrayList<>();
setHasStableIds(true); setHasStableIds(true);
} }
@ -52,7 +55,7 @@ final class StickerKeyboardPageAdapter extends RecyclerView.Adapter<StickerKeybo
@Override @Override
public void onBindViewHolder(@NonNull StickerKeyboardPageViewHolder viewHolder, int i) { public void onBindViewHolder(@NonNull StickerKeyboardPageViewHolder viewHolder, int i) {
viewHolder.bind(glideRequests, eventListener, stickers.get(i), stickerSize); viewHolder.bind(glideRequests, eventListener, stickers.get(i), stickerSize, allowApngAnimation);
} }
@Override @Override
@ -93,7 +96,8 @@ final class StickerKeyboardPageAdapter extends RecyclerView.Adapter<StickerKeybo
public void bind(@NonNull GlideRequests glideRequests, public void bind(@NonNull GlideRequests glideRequests,
@Nullable EventListener eventListener, @Nullable EventListener eventListener,
@NonNull StickerRecord sticker, @NonNull StickerRecord sticker,
@Px int size) @Px int size,
boolean allowApngAnimation)
{ {
currentSticker = sticker; currentSticker = sticker;
@ -102,6 +106,7 @@ final class StickerKeyboardPageAdapter extends RecyclerView.Adapter<StickerKeybo
itemView.requestLayout(); itemView.requestLayout();
glideRequests.load(new DecryptableUri(sticker.getUri())) glideRequests.load(new DecryptableUri(sticker.getUri()))
.set(ApngOptions.ANIMATE, allowApngAnimation)
.transition(DrawableTransitionOptions.withCrossFade()) .transition(DrawableTransitionOptions.withCrossFade())
.into(image); .into(image);

Wyświetl plik

@ -23,6 +23,7 @@ import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.GlideRequests; import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.stickers.StickerKeyboardPageAdapter.StickerKeyboardPageViewHolder; import org.thoughtcrime.securesms.stickers.StickerKeyboardPageAdapter.StickerKeyboardPageViewHolder;
import org.thoughtcrime.securesms.util.DeviceProperties;
import org.whispersystems.libsignal.util.Pair; import org.whispersystems.libsignal.util.Pair;
/** /**
@ -69,7 +70,7 @@ public final class StickerKeyboardPageFragment extends Fragment implements Stick
GlideRequests glideRequests = GlideApp.with(this); GlideRequests glideRequests = GlideApp.with(this);
this.list = view.findViewById(R.id.sticker_keyboard_list); this.list = view.findViewById(R.id.sticker_keyboard_list);
this.adapter = new StickerKeyboardPageAdapter(glideRequests, this); this.adapter = new StickerKeyboardPageAdapter(glideRequests, this, DeviceProperties.shouldAllowApngStickerAnimation(requireContext()));
this.layoutManager = new GridLayoutManager(requireContext(), 2); this.layoutManager = new GridLayoutManager(requireContext(), 2);
this.listTouchListener = new StickerRolloverTouchListener(requireContext(), glideRequests, eventListener, this); this.listTouchListener = new StickerRolloverTouchListener(requireContext(), glideRequests, eventListener, this);
this.packId = getArguments().getString(KEY_PACK_ID); this.packId = getArguments().getString(KEY_PACK_ID);

Wyświetl plik

@ -19,10 +19,12 @@ import org.thoughtcrime.securesms.components.emoji.MediaKeyboardProvider;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.model.StickerPackRecord; import org.thoughtcrime.securesms.database.model.StickerPackRecord;
import org.thoughtcrime.securesms.database.model.StickerRecord; import org.thoughtcrime.securesms.database.model.StickerRecord;
import org.thoughtcrime.securesms.glide.cache.ApngOptions;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
import org.thoughtcrime.securesms.mms.GlideRequests; import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.stickers.StickerKeyboardPageFragment.EventListener; import org.thoughtcrime.securesms.stickers.StickerKeyboardPageFragment.EventListener;
import org.thoughtcrime.securesms.stickers.StickerKeyboardRepository.PackListResult; import org.thoughtcrime.securesms.stickers.StickerKeyboardRepository.PackListResult;
import org.thoughtcrime.securesms.util.DeviceProperties;
import org.thoughtcrime.securesms.util.Throttler; import org.thoughtcrime.securesms.util.Throttler;
import java.util.ArrayList; import java.util.ArrayList;
@ -147,7 +149,7 @@ public final class StickerKeyboardProvider implements MediaKeyboardProvider,
startingIndex = !result.hasRecents() && result.getPacks().size() > 0 ? 1 : 0; startingIndex = !result.hasRecents() && result.getPacks().size() > 0 ? 1 : 0;
} }
presenter.present(this, pagerAdapter, new IconProvider(context, result.getPacks()), null, this, null, startingIndex); presenter.present(this, pagerAdapter, new IconProvider(context, result.getPacks(), DeviceProperties.shouldAllowApngStickerAnimation(context)), null, this, null, startingIndex);
if (isSoloProvider && result.getPacks().isEmpty()) { if (isSoloProvider && result.getPacks().isEmpty()) {
context.startActivity(StickerManagementActivity.getIntent(context)); context.startActivity(StickerManagementActivity.getIntent(context));
@ -238,10 +240,12 @@ public final class StickerKeyboardProvider implements MediaKeyboardProvider,
private final Context context; private final Context context;
private final List<StickerPackRecord> packs; private final List<StickerPackRecord> packs;
private final boolean allowApngAnimation;
private IconProvider(@NonNull Context context, List<StickerPackRecord> packs) { private IconProvider(@NonNull Context context, List<StickerPackRecord> packs, boolean allowApngAnimation) {
this.context = context; this.context = context;
this.packs = packs; this.packs = packs;
this.allowApngAnimation = allowApngAnimation;
} }
@Override @Override
@ -253,6 +257,7 @@ public final class StickerKeyboardProvider implements MediaKeyboardProvider,
Uri uri = packs.get(index - 1).getCover().getUri(); Uri uri = packs.get(index - 1).getCover().getUri();
glideRequests.load(new DecryptableStreamUriLoader.DecryptableUri(uri)) glideRequests.load(new DecryptableStreamUriLoader.DecryptableUri(uri))
.set(ApngOptions.ANIMATE, allowApngAnimation)
.into(imageView); .into(imageView);
} }
} }

Wyświetl plik

@ -15,6 +15,7 @@ import org.thoughtcrime.securesms.PassphraseRequiredActivity;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.sharing.ShareActivity; import org.thoughtcrime.securesms.sharing.ShareActivity;
import org.thoughtcrime.securesms.util.DeviceProperties;
import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.DynamicTheme;
/** /**
@ -93,7 +94,7 @@ public final class StickerManagementActivity extends PassphraseRequiredActivity
private void initView() { private void initView() {
this.list = findViewById(R.id.sticker_management_list); this.list = findViewById(R.id.sticker_management_list);
this.adapter = new StickerManagementAdapter(GlideApp.with(this), this); this.adapter = new StickerManagementAdapter(GlideApp.with(this), this, DeviceProperties.shouldAllowApngStickerAnimation(this));
list.setLayoutManager(new LinearLayoutManager(this)); list.setLayoutManager(new LinearLayoutManager(this));
list.setAdapter(adapter); list.setAdapter(adapter);

Wyświetl plik

@ -21,6 +21,7 @@ import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.emoji.EmojiTextView; import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
import org.thoughtcrime.securesms.database.model.StickerPackRecord; import org.thoughtcrime.securesms.database.model.StickerPackRecord;
import org.thoughtcrime.securesms.glide.cache.ApngOptions;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
import org.thoughtcrime.securesms.mms.GlideRequests; import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.util.adapter.SectionedRecyclerViewAdapter; import org.thoughtcrime.securesms.util.adapter.SectionedRecyclerViewAdapter;
@ -38,6 +39,7 @@ final class StickerManagementAdapter extends SectionedRecyclerViewAdapter<String
private final GlideRequests glideRequests; private final GlideRequests glideRequests;
private final EventListener eventListener; private final EventListener eventListener;
private final boolean allowApngAnimation;
private final List<StickerSection> sections = new ArrayList<StickerSection>(3) {{ private final List<StickerSection> sections = new ArrayList<StickerSection>(3) {{
StickerSection yourStickers = new StickerSection(TAG_YOUR_STICKERS, StickerSection yourStickers = new StickerSection(TAG_YOUR_STICKERS,
@ -55,9 +57,10 @@ final class StickerManagementAdapter extends SectionedRecyclerViewAdapter<String
add(messageStickers); add(messageStickers);
}}; }};
StickerManagementAdapter(@NonNull GlideRequests glideRequests, @NonNull EventListener eventListener) { StickerManagementAdapter(@NonNull GlideRequests glideRequests, @NonNull EventListener eventListener, boolean allowApngAnimation) {
this.glideRequests = glideRequests; this.glideRequests = glideRequests;
this.eventListener = eventListener; this.eventListener = eventListener;
this.allowApngAnimation = allowApngAnimation;
} }
@Override @Override
@ -82,7 +85,7 @@ final class StickerManagementAdapter extends SectionedRecyclerViewAdapter<String
@Override @Override
public void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull StickerSection section, int localPosition) { public void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull StickerSection section, int localPosition) {
section.bindViewHolder(viewHolder, localPosition, glideRequests, eventListener); section.bindViewHolder(viewHolder, localPosition, glideRequests, eventListener, allowApngAnimation);
} }
@Override @Override
@ -198,14 +201,15 @@ final class StickerManagementAdapter extends SectionedRecyclerViewAdapter<String
void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder,
int localPosition, int localPosition,
@NonNull GlideRequests glideRequests, @NonNull GlideRequests glideRequests,
@NonNull EventListener eventListener) @NonNull EventListener eventListener,
boolean allowApngAnimation)
{ {
if (localPosition == 0) { if (localPosition == 0) {
((HeaderViewHolder) viewHolder).bind(titleResId); ((HeaderViewHolder) viewHolder).bind(titleResId);
} else if (records.isEmpty()) { } else if (records.isEmpty()) {
((EmptyViewHolder) viewHolder).bind(emptyResId); ((EmptyViewHolder) viewHolder).bind(emptyResId);
} else { } else {
((StickerViewHolder) viewHolder).bind(glideRequests, eventListener, records.get(localPosition - 1), localPosition == records.size()); ((StickerViewHolder) viewHolder).bind(glideRequests, eventListener, records.get(localPosition - 1), localPosition == records.size(), allowApngAnimation);
} }
} }
@ -254,7 +258,8 @@ final class StickerManagementAdapter extends SectionedRecyclerViewAdapter<String
void bind(@NonNull GlideRequests glideRequests, void bind(@NonNull GlideRequests glideRequests,
@NonNull EventListener eventListener, @NonNull EventListener eventListener,
@NonNull StickerPackRecord stickerPack, @NonNull StickerPackRecord stickerPack,
boolean lastInList) boolean lastInList,
boolean allowApngAnimation)
{ {
title.setText(stickerPack.getTitle().or(itemView.getResources().getString(R.string.StickerManagementAdapter_untitled))); title.setText(stickerPack.getTitle().or(itemView.getResources().getString(R.string.StickerManagementAdapter_untitled)));
author.setText(stickerPack.getAuthor().or(itemView.getResources().getString(R.string.StickerManagementAdapter_unknown))); author.setText(stickerPack.getAuthor().or(itemView.getResources().getString(R.string.StickerManagementAdapter_unknown)));
@ -268,6 +273,7 @@ final class StickerManagementAdapter extends SectionedRecyclerViewAdapter<String
glideRequests.load(new DecryptableUri(stickerPack.getCover().getUri())) glideRequests.load(new DecryptableUri(stickerPack.getCover().getUri()))
.transition(DrawableTransitionOptions.withCrossFade()) .transition(DrawableTransitionOptions.withCrossFade())
.set(ApngOptions.ANIMATE, allowApngAnimation)
.into(cover); .into(cover);
if (stickerPack.isInstalled()) { if (stickerPack.isInstalled()) {

Wyświetl plik

@ -21,10 +21,12 @@ import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.PassphraseRequiredActivity; import org.thoughtcrime.securesms.PassphraseRequiredActivity;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.glide.cache.ApngOptions;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.sharing.ShareActivity; import org.thoughtcrime.securesms.sharing.ShareActivity;
import org.thoughtcrime.securesms.stickers.StickerManifest.Sticker; import org.thoughtcrime.securesms.stickers.StickerManifest.Sticker;
import org.thoughtcrime.securesms.util.DeviceProperties;
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme; import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.DynamicTheme;
import org.whispersystems.libsignal.util.Pair; import org.whispersystems.libsignal.util.Pair;
@ -140,7 +142,7 @@ public final class StickerPackPreviewActivity extends PassphraseRequiredActivity
this.shareButton = findViewById(R.id.sticker_install_share_button); this.shareButton = findViewById(R.id.sticker_install_share_button);
this.shareButtonImage = findViewById(R.id.sticker_install_share_button_image); this.shareButtonImage = findViewById(R.id.sticker_install_share_button_image);
this.adapter = new StickerPackPreviewAdapter(GlideApp.with(this), this); this.adapter = new StickerPackPreviewAdapter(GlideApp.with(this), this, DeviceProperties.shouldAllowApngStickerAnimation(this));
this.layoutManager = new GridLayoutManager(this, 2); this.layoutManager = new GridLayoutManager(this, 2);
this.touchListener = new StickerRolloverTouchListener(this, GlideApp.with(this), this, this); this.touchListener = new StickerRolloverTouchListener(this, GlideApp.with(this), this, this);
onScreenWidthChanged(getScreenWidth()); onScreenWidthChanged(getScreenWidth());
@ -192,6 +194,7 @@ public final class StickerPackPreviewActivity extends PassphraseRequiredActivity
: new StickerRemoteUri(cover.getPackId(), cover.getPackKey(), cover.getId()); : new StickerRemoteUri(cover.getPackId(), cover.getPackKey(), cover.getId());
GlideApp.with(this).load(model) GlideApp.with(this).load(model)
.transition(DrawableTransitionOptions.withCrossFade()) .transition(DrawableTransitionOptions.withCrossFade())
.set(ApngOptions.ANIMATE, DeviceProperties.shouldAllowApngStickerAnimation(this))
.into(coverImage); .into(coverImage);
} else { } else {
coverImage.setImageDrawable(null); coverImage.setImageDrawable(null);

Wyświetl plik

@ -12,6 +12,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions; import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.glide.cache.ApngOptions;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
import org.thoughtcrime.securesms.mms.GlideRequests; import org.thoughtcrime.securesms.mms.GlideRequests;
@ -23,11 +24,13 @@ public final class StickerPackPreviewAdapter extends RecyclerView.Adapter<Sticke
private final GlideRequests glideRequests; private final GlideRequests glideRequests;
private final EventListener eventListener; private final EventListener eventListener;
private final List<StickerManifest.Sticker> list; private final List<StickerManifest.Sticker> list;
private final boolean allowApngAnimation;
public StickerPackPreviewAdapter(@NonNull GlideRequests glideRequests, @NonNull EventListener eventListener) { public StickerPackPreviewAdapter(@NonNull GlideRequests glideRequests, @NonNull EventListener eventListener, boolean allowApngAnimation) {
this.glideRequests = glideRequests; this.glideRequests = glideRequests;
this.eventListener = eventListener; this.eventListener = eventListener;
this.list = new ArrayList<>(); this.allowApngAnimation = allowApngAnimation;
this.list = new ArrayList<>();
} }
@Override @Override
@ -37,7 +40,7 @@ public final class StickerPackPreviewAdapter extends RecyclerView.Adapter<Sticke
@Override @Override
public void onBindViewHolder(@NonNull StickerViewHolder stickerViewHolder, int i) { public void onBindViewHolder(@NonNull StickerViewHolder stickerViewHolder, int i) {
stickerViewHolder.bind(glideRequests, list.get(i), eventListener); stickerViewHolder.bind(glideRequests, list.get(i), eventListener, allowApngAnimation);
} }
@Override @Override
@ -68,12 +71,17 @@ public final class StickerPackPreviewAdapter extends RecyclerView.Adapter<Sticke
this.image = itemView.findViewById(R.id.sticker_install_item_image); this.image = itemView.findViewById(R.id.sticker_install_item_image);
} }
void bind(@NonNull GlideRequests glideRequests, @NonNull StickerManifest.Sticker sticker, @NonNull EventListener eventListener) { void bind(@NonNull GlideRequests glideRequests,
@NonNull StickerManifest.Sticker sticker,
@NonNull EventListener eventListener,
boolean allowApngAnimation)
{
currentEmoji = sticker.getEmoji(); currentEmoji = sticker.getEmoji();
currentGlideModel = sticker.getUri().isPresent() ? new DecryptableStreamUriLoader.DecryptableUri(sticker.getUri().get()) currentGlideModel = sticker.getUri().isPresent() ? new DecryptableStreamUriLoader.DecryptableUri(sticker.getUri().get())
: new StickerRemoteUri(sticker.getPackId(), sticker.getPackKey(), sticker.getId()); : new StickerRemoteUri(sticker.getPackId(), sticker.getPackKey(), sticker.getId());
glideRequests.load(currentGlideModel) glideRequests.load(currentGlideModel)
.transition(DrawableTransitionOptions.withCrossFade()) .transition(DrawableTransitionOptions.withCrossFade())
.set(ApngOptions.ANIMATE, allowApngAnimation)
.into(image); .into(image);
image.setOnLongClickListener(v -> { image.setOnLongClickListener(v -> {

Wyświetl plik

@ -0,0 +1,30 @@
package org.thoughtcrime.securesms.util;
import android.app.ActivityManager;
import android.content.Context;
import androidx.annotation.NonNull;
/**
* Easy access to various properties of the device, typically to make performance-related decisions.
*/
public final class DeviceProperties {
/**
* Whether or not we believe the device has the performance capabilities to efficiently render
* large numbers of APNGs simultaneously.
*/
public static boolean shouldAllowApngStickerAnimation(@NonNull Context context) {
return !isLowMemoryDevice(context) && getMemoryClass(context) >= FeatureFlags.animatedStickerMinimumMemory();
}
public static boolean isLowMemoryDevice(@NonNull Context context) {
ActivityManager activityManager = ServiceUtil.getActivityManager(context);
return activityManager.isLowRamDevice();
}
public static int getMemoryClass(@NonNull Context context) {
ActivityManager activityManager = ServiceUtil.getActivityManager(context);
return activityManager.getMemoryClass();
}
}

Wyświetl plik

@ -72,6 +72,7 @@ public final class FeatureFlags {
private static final String DEFAULT_MAX_BACKOFF = "android.defaultMaxBackoff"; private static final String DEFAULT_MAX_BACKOFF = "android.defaultMaxBackoff";
private static final String OKHTTP_AUTOMATIC_RETRY = "android.okhttpAutomaticRetry"; private static final String OKHTTP_AUTOMATIC_RETRY = "android.okhttpAutomaticRetry";
private static final String SHARE_SELECTION_LIMIT = "android.share.limit"; private static final String SHARE_SELECTION_LIMIT = "android.share.limit";
private static final String ANIMATED_STICKER_MIN_MEMORY = "android.animatedStickerMinMemory";
/** /**
* We will only store remote values for flags in this set. If you want a flag to be controllable * We will only store remote values for flags in this set. If you want a flag to be controllable
@ -100,7 +101,8 @@ public final class FeatureFlags {
AUTOMATIC_SESSION_INTERVAL, AUTOMATIC_SESSION_INTERVAL,
DEFAULT_MAX_BACKOFF, DEFAULT_MAX_BACKOFF,
OKHTTP_AUTOMATIC_RETRY, OKHTTP_AUTOMATIC_RETRY,
SHARE_SELECTION_LIMIT SHARE_SELECTION_LIMIT,
ANIMATED_STICKER_MIN_MEMORY
); );
@VisibleForTesting @VisibleForTesting
@ -139,7 +141,8 @@ public final class FeatureFlags {
AUTOMATIC_SESSION_INTERVAL, AUTOMATIC_SESSION_INTERVAL,
DEFAULT_MAX_BACKOFF, DEFAULT_MAX_BACKOFF,
OKHTTP_AUTOMATIC_RETRY, OKHTTP_AUTOMATIC_RETRY,
SHARE_SELECTION_LIMIT SHARE_SELECTION_LIMIT,
ANIMATED_STICKER_MIN_MEMORY
); );
/** /**
@ -324,6 +327,11 @@ public final class FeatureFlags {
return getBoolean(OKHTTP_AUTOMATIC_RETRY, false); return getBoolean(OKHTTP_AUTOMATIC_RETRY, false);
} }
/** The minimum amount of memory required for rendering animated stickers in the keyboard and such */
public static int animatedStickerMinimumMemory() {
return getInteger(ANIMATED_STICKER_MIN_MEMORY, 193);
}
/** Only for rendering debug info. */ /** Only for rendering debug info. */
public static synchronized @NonNull Map<String, Object> getMemoryValues() { public static synchronized @NonNull Map<String, Object> getMemoryValues() {
return new TreeMap<>(REMOTE_VALUES); return new TreeMap<>(REMOTE_VALUES);