Convert LogSectionSystemInfo to kotlin.

This commit is contained in:
Greyson Parrelli
2025-11-05 10:09:50 -05:00
committed by Michelle Tang
parent 677686fa40
commit 9138a8972f
2 changed files with 187 additions and 213 deletions

View File

@@ -1,213 +0,0 @@
package org.thoughtcrime.securesms.logsubmit;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import org.signal.core.util.FontUtil;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.dependencies.AppDependencies;
import org.thoughtcrime.securesms.emoji.EmojiFiles;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.net.StandardUserAgentInterceptor;
import org.thoughtcrime.securesms.notifications.SlowNotificationHeuristics;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.webrtc.AndroidTelecomUtil;
import org.thoughtcrime.securesms.util.AppSignatureUtil;
import org.thoughtcrime.securesms.util.ByteUnit;
import org.thoughtcrime.securesms.util.ContextUtil;
import org.thoughtcrime.securesms.util.DeviceProperties;
import org.thoughtcrime.securesms.util.NetworkUtil;
import org.thoughtcrime.securesms.util.PowerManagerCompat;
import org.thoughtcrime.securesms.util.ScreenDensity;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.VersionTracker;
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Locale;
import static org.thoughtcrime.securesms.window.WindowSizeClassExtensionsKt.getWindowSizeClass;
public class LogSectionSystemInfo implements LogSection {
@Override
public @NonNull String getTitle() {
return "SYSINFO";
}
@Override
public @NonNull CharSequence getContent(@NonNull Context context) {
final PackageManager pm = context.getPackageManager();
final StringBuilder builder = new StringBuilder();
builder.append("Time : ").append(System.currentTimeMillis()).append('\n');
builder.append("Manufacturer : ").append(Build.MANUFACTURER).append("\n");
builder.append("Model : ").append(Build.MODEL).append("\n");
builder.append("Product : ").append(Build.PRODUCT).append("\n");
builder.append("SoC Manufacturer : ").append(Build.VERSION.SDK_INT >= 31 ? Build.SOC_MANUFACTURER : "N/A").append("\n");
builder.append("SoC Model : ").append(Build.VERSION.SDK_INT >= 31 ? Build.SOC_MODEL : "N/A").append("\n");
builder.append("Screen : ").append(getScreenResolution(context)).append(", ")
.append(ScreenDensity.get(context)).append(", ")
.append(getScreenRefreshRate(context)).append("\n");
builder.append("WindowSizeClass : ").append(getWindowSizeClass(context.getResources())).append("\n");
builder.append("Font Scale : ").append(context.getResources().getConfiguration().fontScale).append("\n");
builder.append("Animation Scale : ").append(ContextUtil.getAnimationScale(context)).append("\n");
builder.append("Android : ").append(Build.VERSION.RELEASE).append(", API ")
.append(Build.VERSION.SDK_INT).append(" (")
.append(Build.VERSION.INCREMENTAL).append(", ")
.append(Build.DISPLAY).append(")\n");
builder.append("ABIs : ").append(TextUtils.join(", ", getSupportedAbis())).append("\n");
builder.append("Memory : ").append(getMemoryUsage()).append("\n");
builder.append("Memclass : ").append(getMemoryClass(context)).append("\n");
builder.append("MemInfo : ").append(getMemoryInfo(context)).append("\n");
builder.append("OS Host : ").append(Build.HOST).append("\n");
builder.append("RecipientId : ").append(SignalStore.registration().isRegistrationComplete() ? Recipient.self().getId() : "N/A").append("\n");
builder.append("ACI : ").append(getCensoredAci(context)).append("\n");
builder.append("Device ID : ").append(SignalStore.account().getDeviceId()).append("\n");
builder.append("Censored : ").append(AppDependencies.getSignalServiceNetworkAccess().isCensored()).append("\n");
builder.append("Network Status : ").append(NetworkUtil.getNetworkStatus(context)).append("\n");
builder.append("Play Services : ").append(getPlayServicesString(context)).append("\n");
builder.append("FCM : ").append(SignalStore.account().isFcmEnabled()).append("\n");
builder.append("Locale : ").append(Locale.getDefault()).append("\n");
builder.append("Linked Devices : ").append(SignalStore.account().isMultiDevice()).append("\n");
builder.append("First Version : ").append(TextSecurePreferences.getFirstInstallVersion(context)).append("\n");
builder.append("Days Installed : ").append(VersionTracker.getDaysSinceFirstInstalled(context)).append("\n");
builder.append("Build Variant : ").append(BuildConfig.BUILD_DISTRIBUTION_TYPE).append(BuildConfig.BUILD_ENVIRONMENT_TYPE).append(BuildConfig.BUILD_VARIANT_TYPE).append("\n");
builder.append("Emoji Version : ").append(getEmojiVersionString(context)).append("\n");
builder.append("RenderBigEmoji : ").append(FontUtil.canRenderEmojiAtFontSize(1024)).append("\n");
builder.append("DontKeepActivities: ").append(getDontKeepActivities(context)).append("\n");
builder.append("Server Time Offset: ").append(SignalStore.misc().getLastKnownServerTimeOffset()).append(" ms (last updated: ").append(SignalStore.misc().getLastKnownServerTimeOffsetUpdateTime()).append(")").append("\n");
builder.append("Telecom : ").append(AndroidTelecomUtil.getTelecomSupported()).append("\n");
builder.append("User-Agent : ").append(StandardUserAgentInterceptor.USER_AGENT).append("\n");
builder.append("SlowNotifications : ").append(SlowNotificationHeuristics.isHavingDelayedNotifications()).append("\n");
builder.append("IgnoringBatteryOpt: ").append(PowerManagerCompat.isIgnoringBatteryOptimizations(context)).append("\n");
builder.append("BkgRestricted : ").append(Build.VERSION.SDK_INT >= 28 ? DeviceProperties.isBackgroundRestricted(context) : "N/A").append("\n");
builder.append("Data Saver : ").append(DeviceProperties.getDataSaverState(context)).append("\n");
builder.append("APNG Animation : ").append(DeviceProperties.shouldAllowApngStickerAnimation(context)).append("\n");
if (BuildConfig.MANAGES_APP_UPDATES) {
builder.append("ApkManifestUrl : ").append(BuildConfig.APK_UPDATE_MANIFEST_URL).append("\n");
}
builder.append("App : ");
try {
builder.append(pm.getApplicationLabel(pm.getApplicationInfo(context.getPackageName(), 0)))
.append(" ")
.append(pm.getPackageInfo(context.getPackageName(), 0).versionName)
.append(" (")
.append(BuildConfig.CANONICAL_VERSION_CODE)
.append(", ")
.append(Util.getManifestApkVersion(context))
.append(") (")
.append(BuildConfig.GIT_HASH).append(") \n");
} catch (PackageManager.NameNotFoundException nnfe) {
builder.append("Unknown\n");
}
builder.append("Package : ").append(BuildConfig.APPLICATION_ID).append(" (").append(getSigningString(context)).append(")");
return builder;
}
private static @NonNull String getMemoryUsage() {
Runtime info = Runtime.getRuntime();
long totalMemory = info.totalMemory();
return String.format(Locale.ENGLISH,
"%dM (%.2f%% free, %dM max)",
ByteUnit.BYTES.toMegabytes(totalMemory),
(float) info.freeMemory() / totalMemory * 100f,
ByteUnit.BYTES.toMegabytes(info.maxMemory()));
}
private static @NonNull String getMemoryClass(Context context) {
ActivityManager activityManager = ServiceUtil.getActivityManager(context);
String lowMem = "";
if (activityManager.isLowRamDevice()) {
lowMem = ", low-mem device";
}
return activityManager.getMemoryClass() + lowMem;
}
private static @NonNull String getMemoryInfo(Context context) {
ActivityManager.MemoryInfo info = DeviceProperties.getMemoryInfo(context);
return String.format(Locale.US, "availMem: %d mb, totalMem: %d mb, threshold: %d mb, lowMemory: %b",
ByteUnit.BYTES.toMegabytes(info.availMem), ByteUnit.BYTES.toMegabytes(info.totalMem), ByteUnit.BYTES.toMegabytes(info.threshold), info.lowMemory);
}
private static @NonNull Iterable<String> getSupportedAbis() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return Arrays.asList(Build.SUPPORTED_ABIS);
} else {
LinkedList<String> abis = new LinkedList<>();
abis.add(Build.CPU_ABI);
if (Build.CPU_ABI2 != null && !"unknown".equals(Build.CPU_ABI2)) {
abis.add(Build.CPU_ABI2);
}
return abis;
}
}
private static @NonNull String getScreenResolution(@NonNull Context context) {
DisplayMetrics displayMetrics = new DisplayMetrics();
WindowManager windowManager = ServiceUtil.getWindowManager(context);
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.widthPixels + "x" + displayMetrics.heightPixels;
}
private static @NonNull String getScreenRefreshRate(@NonNull Context context) {
return String.format(Locale.ENGLISH, "%.2f hz", ServiceUtil.getWindowManager(context).getDefaultDisplay().getRefreshRate());
}
private static String getSigningString(@NonNull Context context) {
return AppSignatureUtil.getAppSignature(context);
}
private static String getPlayServicesString(@NonNull Context context) {
int result = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context);
return result == ConnectionResult.SUCCESS ? "true" : "false (" + result + ")";
}
private static String getEmojiVersionString(@NonNull Context context) {
EmojiFiles.Version version = EmojiFiles.Version.readVersion(context);
if (version == null) {
return "None";
} else {
return version.getVersion() + " (" + version.getDensity() + ")";
}
}
private static String getCensoredAci(@NonNull Context context) {
ACI aci = SignalStore.account().getAci();
if (aci != null) {
String aciString = aci.toString();
String lastThree = aciString.substring(aciString.length() - 3);
return "********-****-****-****-*********" + lastThree;
} else {
return "N/A";
}
}
private static String getDontKeepActivities(@NonNull Context context) {
int setting = Settings.Global.getInt(context.getContentResolver(), Settings.Global.ALWAYS_FINISH_ACTIVITIES, 0);
return setting == 0 ? "false" : "true";
}
}

View File

@@ -0,0 +1,187 @@
package org.thoughtcrime.securesms.logsubmit
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.provider.Settings
import android.util.DisplayMetrics
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import org.signal.core.util.FontUtil.canRenderEmojiAtFontSize
import org.signal.core.util.bytes
import org.signal.core.util.roundedString
import org.thoughtcrime.securesms.BuildConfig
import org.thoughtcrime.securesms.dependencies.AppDependencies.signalServiceNetworkAccess
import org.thoughtcrime.securesms.emoji.EmojiFiles.Version.Companion.readVersion
import org.thoughtcrime.securesms.keyvalue.SignalStore.Companion.account
import org.thoughtcrime.securesms.keyvalue.SignalStore.Companion.misc
import org.thoughtcrime.securesms.keyvalue.SignalStore.Companion.registration
import org.thoughtcrime.securesms.net.StandardUserAgentInterceptor
import org.thoughtcrime.securesms.notifications.SlowNotificationHeuristics.isHavingDelayedNotifications
import org.thoughtcrime.securesms.recipients.Recipient.Companion.self
import org.thoughtcrime.securesms.service.webrtc.AndroidTelecomUtil.telecomSupported
import org.thoughtcrime.securesms.util.AppSignatureUtil
import org.thoughtcrime.securesms.util.ContextUtil
import org.thoughtcrime.securesms.util.DeviceProperties
import org.thoughtcrime.securesms.util.NetworkUtil
import org.thoughtcrime.securesms.util.PowerManagerCompat
import org.thoughtcrime.securesms.util.ScreenDensity
import org.thoughtcrime.securesms.util.ServiceUtil
import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.thoughtcrime.securesms.util.Util
import org.thoughtcrime.securesms.util.VersionTracker.getDaysSinceFirstInstalled
import org.thoughtcrime.securesms.window.getWindowSizeClass
import java.util.Locale
class LogSectionSystemInfo : LogSection {
override fun getTitle(): String {
return "SYSINFO"
}
override fun getContent(context: Context): CharSequence {
return """
Time : ${System.currentTimeMillis()}
Manufacturer : ${Build.MANUFACTURER}
Model : ${Build.MODEL}
Product : ${Build.PRODUCT}
SoC Manufacturer : ${if (Build.VERSION.SDK_INT >= 31) Build.SOC_MANUFACTURER else "N/A"}
SoC Model : ${if (Build.VERSION.SDK_INT >= 31) Build.SOC_MODEL else "N/A"}
Screen : ${getScreenResolution(context)}, ${ScreenDensity.get(context)}, ${getScreenRefreshRate(context)}
WindowSizeClass : ${context.resources.getWindowSizeClass()}
Font Scale : ${context.resources.configuration.fontScale}
Animation Scale : ${ContextUtil.getAnimationScale(context)}
Android : ${Build.VERSION.RELEASE}, API ${Build.VERSION.SDK_INT} (${Build.VERSION.INCREMENTAL}, ${Build.DISPLAY})
ABIs : ${Build.SUPPORTED_ABIS.joinToString(separator = ", ")}
Memory : ${getMemoryUsage()}
Memclass : ${getMemoryClass(context)}
MemInfo : ${getMemoryInfo(context)}
OS Host : ${Build.HOST}
RecipientId : ${if (registration.isRegistrationComplete) self().id else "N/A"}
ACI : ${getCensoredAci()}
Device ID : ${account.deviceId}
Censored : ${signalServiceNetworkAccess.isCensored()}
Network Status : ${NetworkUtil.getNetworkStatus(context)}
Play Services : ${getPlayServicesString(context)}
FCM : ${account.fcmEnabled}
Locale : ${Locale.getDefault()}
Linked Devices : ${account.isMultiDevice}
First Version : ${TextSecurePreferences.getFirstInstallVersion(context)}
Days Installed : ${getDaysSinceFirstInstalled(context)}
Build Variant : ${BuildConfig.BUILD_DISTRIBUTION_TYPE}${BuildConfig.BUILD_ENVIRONMENT_TYPE}${BuildConfig.BUILD_VARIANT_TYPE}
Emoji Version : ${getEmojiVersionString(context)}
RenderBigEmoji : ${canRenderEmojiAtFontSize(1024f)}
DontKeepActivities: ${getDontKeepActivities(context)}
Server Time Offset: ${misc.lastKnownServerTimeOffset} ms (last updated: ${misc.lastKnownServerTimeOffsetUpdateTime})
Telecom : $telecomSupported
User-Agent : ${StandardUserAgentInterceptor.USER_AGENT}
SlowNotifications : ${isHavingDelayedNotifications()}
IgnoringBatteryOpt: ${PowerManagerCompat.isIgnoringBatteryOptimizations(context)}
BkgRestricted : ${if (Build.VERSION.SDK_INT >= 28) DeviceProperties.isBackgroundRestricted(context) else "N/A"}
Data Saver : ${DeviceProperties.getDataSaverState(context)}
APNG Animation : ${DeviceProperties.shouldAllowApngStickerAnimation(context)}
ApkManifestUrl : ${BuildConfig.APK_UPDATE_MANIFEST_URL?.takeIf { BuildConfig.MANAGES_APP_UPDATES } ?: "N/A"}
App : ${getAppInfo(context)}
Package : ${BuildConfig.APPLICATION_ID} (${getSigningString(context)})
""".trimIndent()
}
private fun getAppInfo(context: Context): String {
return try {
val packageManager = context.packageManager
val appLabel = packageManager.getApplicationLabel(packageManager.getApplicationInfo(context.packageName, 0))
val versionName = packageManager.getPackageInfo(context.packageName, 0).versionName
val manifestApkVersion = Util.getManifestApkVersion(context)
"$appLabel $versionName (${BuildConfig.CANONICAL_VERSION_CODE}, $manifestApkVersion) (${BuildConfig.GIT_HASH})"
} catch (_: PackageManager.NameNotFoundException) {
"Unknown"
}
}
private fun getMemoryUsage(): String {
val info = Runtime.getRuntime()
val totalMemory = info.totalMemory()
return String.format(
Locale.ENGLISH,
"%.0fM (%.2f%% free, %.0fM max)",
totalMemory.bytes.inMebiBytes,
info.freeMemory().toFloat() / totalMemory * 100f,
info.maxMemory().bytes.inMebiBytes
)
}
private fun getMemoryClass(context: Context): String {
val activityManager = ServiceUtil.getActivityManager(context)
var lowMem = ""
if (activityManager.isLowRamDevice) {
lowMem = ", low-mem device"
}
return activityManager.memoryClass.toString() + lowMem
}
private fun getMemoryInfo(context: Context): String {
val info = DeviceProperties.getMemoryInfo(context)
return "availMem: ${info.availMem.bytes.inMebiBytes.roundedString(2)} MiB, totalMem: ${info.totalMem.bytes.inMebiBytes.roundedString(2)} MiB, threshold: ${info.threshold.bytes.inMebiBytes.roundedString(2)} MiB, lowMemory: ${info.lowMemory}"
}
private fun getScreenResolution(context: Context): String {
val displayMetrics = DisplayMetrics()
val windowManager = ServiceUtil.getWindowManager(context)
windowManager.defaultDisplay.getMetrics(displayMetrics)
return displayMetrics.widthPixels.toString() + "x" + displayMetrics.heightPixels
}
private fun getScreenRefreshRate(context: Context): String {
return String.format(Locale.ENGLISH, "%.2f hz", ServiceUtil.getWindowManager(context).defaultDisplay.refreshRate)
}
private fun getSigningString(context: Context): String {
return AppSignatureUtil.getAppSignature(context)
}
private fun getPlayServicesString(context: Context): String {
val result = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
return if (result == ConnectionResult.SUCCESS) {
"true"
} else {
"false ($result)"
}
}
private fun getEmojiVersionString(context: Context): String {
val version = readVersion(context)
return if (version == null) {
"None"
} else {
"${version.version} (${version.density})"
}
}
private fun getCensoredAci(): String {
val aci = account.aci
if (aci != null) {
val aciString = aci.toString()
val lastThree = aciString.substring(aciString.length - 3)
return "********-****-****-****-*********$lastThree"
} else {
return "N/A"
}
}
private fun getDontKeepActivities(context: Context): String {
val setting = Settings.Global.getInt(context.contentResolver, Settings.Global.ALWAYS_FINISH_ACTIVITIES, 0)
return if (setting == 0) {
"false"
} else {
"true"
}
}
}