Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add API to retrieve Android scope data #2814

Merged
merged 10 commits into from
Jul 18, 2023
19 changes: 19 additions & 0 deletions sentry-android-core/api/sentry-android-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ public final class io/sentry/android/core/BuildInfoProvider {
public fun isEmulator ()Ljava/lang/Boolean;
}

public final class io/sentry/android/core/ContextUtils {
}

public class io/sentry/android/core/CurrentActivityHolder {
public fun clearActivity ()V
public fun getActivity ()Landroid/app/Activity;
Expand All @@ -148,6 +151,15 @@ public final class io/sentry/android/core/CurrentActivityIntegration : android/a
public fun register (Lio/sentry/IHub;Lio/sentry/SentryOptions;)V
}

public final class io/sentry/android/core/DeviceInfoUtil {
public fun <init> (Landroid/content/Context;Lio/sentry/android/core/SentryAndroidOptions;)V
public fun collectDeviceInformation (ZZ)Lio/sentry/protocol/Device;
public static fun getInstance (Landroid/content/Context;Lio/sentry/android/core/SentryAndroidOptions;)Lio/sentry/android/core/DeviceInfoUtil;
public fun getOperatingSystem ()Lio/sentry/protocol/OperatingSystem;
public fun getSideLoadedInfo ()Lio/sentry/android/core/ContextUtils$SideLoadedInfo;
public static fun resetInstance ()V
}

public abstract class io/sentry/android/core/EnvelopeFileObserverIntegration : io/sentry/Integration, java/io/Closeable {
public fun <init> ()V
public fun close ()V
Expand All @@ -160,6 +172,13 @@ public abstract interface class io/sentry/android/core/IDebugImagesLoader {
public abstract fun loadDebugImages ()Ljava/util/List;
}

public final class io/sentry/android/core/InternalSentrySdk {
public fun <init> ()V
public static fun captureEnvelope ([B)Lio/sentry/protocol/SentryId;
public static fun getCurrentScope ()Lio/sentry/Scope;
public static fun serializeScope (Landroid/content/Context;Lio/sentry/android/core/SentryAndroidOptions;Lio/sentry/Scope;)Ljava/util/Map;
}

public final class io/sentry/android/core/LoadClass {
public fun <init> ()V
public fun isClassAvailable (Ljava/lang/String;Lio/sentry/ILogger;)Z
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -524,11 +524,12 @@ private void mergeUser(final @NotNull SentryBaseEvent event) {

private void setSideLoadedInfo(final @NotNull SentryBaseEvent event) {
try {
final Map<String, String> sideLoadedInfo =
ContextUtils.getSideLoadedInfo(context, options.getLogger(), buildInfoProvider);
final ContextUtils.SideLoadedInfo sideLoadedInfo =
ContextUtils.retrieveSideLoadedInfo(context, options.getLogger(), buildInfoProvider);

if (sideLoadedInfo != null) {
for (final Map.Entry<String, String> entry : sideLoadedInfo.entrySet()) {
final @NotNull Map<String, String> tags = sideLoadedInfo.asTags();
for (Map.Entry<String, String> entry : tags.entrySet()) {
event.setTag(entry.getKey(), entry.getValue());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static android.content.Context.ACTIVITY_SERVICE;
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;

import android.annotation.SuppressLint;
import android.app.ActivityManager;
Expand All @@ -15,17 +16,47 @@
import android.util.DisplayMetrics;
import io.sentry.ILogger;
import io.sentry.SentryLevel;
import io.sentry.protocol.App;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

final class ContextUtils {
@ApiStatus.Internal
public final class ContextUtils {

static class SideLoadedInfo {
private final boolean isSideLoaded;
private final @Nullable String installerStore;

public SideLoadedInfo(final boolean isSideLoaded, final @Nullable String installerStore) {
this.isSideLoaded = isSideLoaded;
this.installerStore = installerStore;
}

public boolean isSideLoaded() {
return isSideLoaded;
}

public @Nullable String getInstallerStore() {
return installerStore;
}

public @NotNull Map<String, String> asTags() {
final Map<String, String> data = new HashMap<>();
data.put("isSideLoaded", String.valueOf(isSideLoaded));
if (installerStore != null) {
data.put("installerStore", installerStore);
}
return data;
}
}

private ContextUtils() {}

Expand Down Expand Up @@ -187,8 +218,8 @@ static boolean isForegroundImportance(final @NotNull Context context) {
return defaultVersion;
}

@SuppressWarnings("deprecation")
static @Nullable Map<String, String> getSideLoadedInfo(
@SuppressWarnings({"deprecation"})
static @Nullable SideLoadedInfo retrieveSideLoadedInfo(
final @NotNull Context context,
final @NotNull ILogger logger,
final @NotNull BuildInfoProvider buildInfoProvider) {
Expand All @@ -202,20 +233,10 @@ static boolean isForegroundImportance(final @NotNull Context context) {

// getInstallSourceInfo requires INSTALL_PACKAGES permission which is only given to system
// apps.
// if it's installed via adb, system apps or untrusted sources
// could be amazon, google play etc - or null in case of sideload
final String installerPackageName = packageManager.getInstallerPackageName(packageName);

final Map<String, String> sideLoadedInfo = new HashMap<>();

if (installerPackageName != null) {
sideLoadedInfo.put("isSideLoaded", "false");
// could be amazon, google play etc
sideLoadedInfo.put("installerStore", installerPackageName);
} else {
// if it's installed via adb, system apps or untrusted sources
sideLoadedInfo.put("isSideLoaded", "true");
}

return sideLoadedInfo;
return new SideLoadedInfo(installerPackageName == null, installerPackageName);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can put the check inside the constructor, so that you can pass only one parameter

}
} catch (IllegalArgumentException e) {
// it'll never be thrown as we are querying its own App's package.
Expand Down Expand Up @@ -324,4 +345,37 @@ static boolean isForegroundImportance(final @NotNull Context context) {
return null;
}
}

// we perform an if-check for that, but lint fails to recognize
@SuppressLint("NewApi")
static void setAppPackageInfo(
final @NotNull PackageInfo packageInfo,
final @NotNull BuildInfoProvider buildInfoProvider,
final @NotNull App app) {
app.setAppIdentifier(packageInfo.packageName);
app.setAppVersion(packageInfo.versionName);
app.setAppBuild(ContextUtils.getVersionCode(packageInfo, buildInfoProvider));

if (buildInfoProvider.getSdkInfoVersion() >= Build.VERSION_CODES.JELLY_BEAN) {
final Map<String, String> permissions = new HashMap<>();
final String[] requestedPermissions = packageInfo.requestedPermissions;
final int[] requestedPermissionsFlags = packageInfo.requestedPermissionsFlags;

if (requestedPermissions != null
&& requestedPermissions.length > 0
&& requestedPermissionsFlags != null
&& requestedPermissionsFlags.length > 0) {
for (int i = 0; i < requestedPermissions.length; i++) {
String permission = requestedPermissions[i];
permission = permission.substring(permission.lastIndexOf('.') + 1);

final boolean granted =
(requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED)
== REQUESTED_PERMISSION_GRANTED;
permissions.put(permission, granted ? "granted" : "not_granted");
}
}
app.setPermissions(permissions);
}
}
}