Skip to content

Commit

Permalink
Merge 4319ed5 into 3e773a7
Browse files Browse the repository at this point in the history
  • Loading branch information
marandaneto authored Feb 7, 2023
2 parents 3e773a7 + 4319ed5 commit a4ccef1
Show file tree
Hide file tree
Showing 11 changed files with 152 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public DefaultAndroidEventProcessor(
this.options = Objects.requireNonNull(options, "The options object is required.");

ExecutorService executorService = Executors.newSingleThreadExecutor();
// dont ref. to method reference, theres a bug on it
// don't ref. to method reference, theres a bug on it
//noinspection Convert2MethodRef
contextData = executorService.submit(() -> loadContextData());

Expand Down Expand Up @@ -128,8 +128,8 @@ public DefaultAndroidEventProcessor(
// we only set memory data if it's not a hard crash, when it's a hard crash the event is
// enriched on restart, so non static data might be wrong, eg lowMemory or availMem will
// be different if the App. crashes because of OOM.
processNonCachedEvent(event);
setThreads(event);
processNonCachedEvent(event, hint);
setThreads(event, hint);
}

setCommons(event, true, applyScopeData);
Expand Down Expand Up @@ -201,23 +201,34 @@ private void mergeOS(final @NotNull SentryBaseEvent event) {
}

// Data to be applied to events that was created in the running process
private void processNonCachedEvent(final @NotNull SentryBaseEvent event) {
private void processNonCachedEvent(
final @NotNull SentryBaseEvent event, final @NotNull Hint hint) {
App app = event.getContexts().getApp();
if (app == null) {
app = new App();
}
setAppExtras(app);
setAppExtras(app, hint);

setPackageInfo(event, app);

event.getContexts().setApp(app);
}

private void setThreads(final @NotNull SentryEvent event) {
private void setThreads(final @NotNull SentryEvent event, final @NotNull Hint hint) {
if (event.getThreads() != null) {
for (SentryThread thread : event.getThreads()) {
final boolean isHybridSDK = HintUtils.isFromHybridSdk(hint);

for (final SentryThread thread : event.getThreads()) {
final boolean isMainThread = AndroidMainThreadChecker.getInstance().isMainThread(thread);

// TODO: Fix https://github.com/getsentry/team-mobile/issues/47
if (thread.isCurrent() == null) {
thread.setCurrent(AndroidMainThreadChecker.getInstance().isMainThread(thread));
thread.setCurrent(isMainThread);
}

// This should not be set by Hybrid SDKs since they have their own threading model
if (!isHybridSDK && thread.isMain() == null) {
thread.setMain(isMainThread);
}
}
}
Expand All @@ -241,9 +252,19 @@ private void setDist(final @NotNull SentryBaseEvent event, final @NotNull String
}
}

private void setAppExtras(final @NotNull App app) {
private void setAppExtras(final @NotNull App app, final @NotNull Hint hint) {
app.setAppName(getApplicationName());
app.setAppStartTime(DateUtils.toUtilDate(AppStartState.getInstance().getAppStartTime()));

// This should not be set by Hybrid SDKs since they have their own app's lifecycle
if (!HintUtils.isFromHybridSdk(hint) && app.getInForeground() == null) {
// This feature depends on the AppLifecycleIntegration being installed, so only if
// enableAutoSessionTracking or enableAppLifecycleBreadcrumbs are enabled.
final @Nullable Boolean isBackground = AppState.getInstance().isInBackground();
if (isBackground != null) {
app.setInForeground(!isBackground);
}
}
}

@SuppressWarnings("deprecation")
Expand All @@ -256,21 +277,21 @@ private void setAppExtras(final @NotNull App app) {
return Build.CPU_ABI2;
}

@SuppressWarnings({"ObsoleteSdkInt", "deprecation"})
@SuppressWarnings({"ObsoleteSdkInt", "deprecation", "NewApi"})
private void setArchitectures(final @NotNull Device device) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
String[] supportedAbis = Build.SUPPORTED_ABIS;
device.setArchs(supportedAbis);
final String[] supportedAbis;
if (buildInfoProvider.getSdkInfoVersion() >= Build.VERSION_CODES.LOLLIPOP) {
supportedAbis = Build.SUPPORTED_ABIS;
} else {
String[] supportedAbis = {getAbi(), getAbi2()};
device.setArchs(supportedAbis);
supportedAbis = new String[] {getAbi(), getAbi2()};
// we were not checking CPU_ABI2, but I've added to the list now
}
device.setArchs(supportedAbis);
}

@SuppressWarnings("ObsoleteSdkInt")
@SuppressWarnings({"ObsoleteSdkInt", "NewApi"})
private @NotNull Long getMemorySize(final @NotNull ActivityManager.MemoryInfo memInfo) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
if (buildInfoProvider.getSdkInfoVersion() >= Build.VERSION_CODES.JELLY_BEAN) {
return memInfo.totalMem;
}
// using Runtime as a fallback
Expand Down Expand Up @@ -393,17 +414,18 @@ private void setDeviceIO(final @NotNull Device device, final boolean applyScopeD
}
}

@SuppressWarnings("ObsoleteSdkInt")
@SuppressWarnings({"ObsoleteSdkInt", "NewApi"})
private @Nullable String getDeviceName() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
if (buildInfoProvider.getSdkInfoVersion() >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
return Settings.Global.getString(context.getContentResolver(), "device_name");
} else {
return null;
}
}

@SuppressWarnings("NewApi")
private TimeZone getTimeZone() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
if (buildInfoProvider.getSdkInfoVersion() >= Build.VERSION_CODES.N) {
LocaleList locales = context.getResources().getConfiguration().getLocales();
if (!locales.isEmpty()) {
Locale locale = locales.get(0);
Expand Down Expand Up @@ -557,9 +579,9 @@ private TimeZone getTimeZone() {
}
}

@SuppressWarnings("ObsoleteSdkInt")
@SuppressWarnings({"ObsoleteSdkInt", "NewApi"})
private long getBlockSizeLong(final @NotNull StatFs stat) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
if (buildInfoProvider.getSdkInfoVersion() >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
return stat.getBlockSizeLong();
}
return getBlockSizeDep(stat);
Expand All @@ -570,9 +592,9 @@ private int getBlockSizeDep(final @NotNull StatFs stat) {
return stat.getBlockSize();
}

@SuppressWarnings("ObsoleteSdkInt")
@SuppressWarnings({"ObsoleteSdkInt", "NewApi"})
private long getBlockCountLong(final @NotNull StatFs stat) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
if (buildInfoProvider.getSdkInfoVersion() >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
return stat.getBlockCountLong();
}
return getBlockCountDep(stat);
Expand All @@ -583,9 +605,9 @@ private int getBlockCountDep(final @NotNull StatFs stat) {
return stat.getBlockCount();
}

@SuppressWarnings("ObsoleteSdkInt")
@SuppressWarnings({"ObsoleteSdkInt", "NewApi"})
private long getAvailableBlocksLong(final @NotNull StatFs stat) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
if (buildInfoProvider.getSdkInfoVersion() >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
return stat.getAvailableBlocksLong();
}
return getAvailableBlocksDep(stat);
Expand Down Expand Up @@ -627,9 +649,9 @@ private int getAvailableBlocksDep(final @NotNull StatFs stat) {
return null;
}

@SuppressWarnings("ObsoleteSdkInt")
@SuppressWarnings({"ObsoleteSdkInt", "NewApi"})
private @Nullable File[] getExternalFilesDirs() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (buildInfoProvider.getSdkInfoVersion() >= Build.VERSION_CODES.KITKAT) {
return context.getExternalFilesDirs(null);
} else {
File single = context.getExternalFilesDir(null);
Expand Down Expand Up @@ -907,7 +929,7 @@ private void setSideLoadedInfo(final @NotNull SentryBaseEvent event) {
final boolean applyScopeData = shouldApplyScopeData(transaction, hint);

if (applyScopeData) {
processNonCachedEvent(transaction);
processNonCachedEvent(transaction, hint);
}

setCommons(transaction, false, applyScopeData);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ final class LifecycleWatcher implements DefaultLifecycleObserver {
public void onStart(final @NotNull LifecycleOwner owner) {
startSession();
addAppBreadcrumb("foreground");

// Consider using owner.getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED);
// in the future.
AppState.getInstance().setInBackground(false);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class DefaultAndroidEventProcessorTest {
private class Fixture {
val buildInfo = mock<BuildInfoProvider>()
val options = SentryAndroidOptions().apply {
setDebug(true)
isDebug = true
setLogger(mock())
sdkVersion = SdkVersion("test", "1.2.3")
}
Expand All @@ -77,6 +77,7 @@ class DefaultAndroidEventProcessorTest {
@BeforeTest
fun `set up`() {
context = ApplicationProvider.getApplicationContext()
AppState.getInstance().resetInstance()
}

@Test
Expand Down Expand Up @@ -161,7 +162,7 @@ class DefaultAndroidEventProcessorTest {
}

@Test
fun `Current should be true if it comes from main thread`() {
fun `Current and Main should be true if it comes from main thread`() {
val sut = fixture.getSut(context)

val sentryThread = SentryThread().apply {
Expand All @@ -174,6 +175,7 @@ class DefaultAndroidEventProcessorTest {
assertNotNull(sut.process(event, Hint())) {
assertNotNull(it.threads) { threads ->
assertTrue(threads.first().isCurrent == true)
assertTrue(threads.first().isMain == true)
}
}
}
Expand All @@ -193,6 +195,7 @@ class DefaultAndroidEventProcessorTest {
assertNotNull(sut.process(event, Hint())) {
assertNotNull(it.threads) { threads ->
assertFalse(threads.first().isCurrent == true)
assertFalse(threads.first().isMain == true)
}
}
}
Expand Down Expand Up @@ -497,4 +500,28 @@ class DefaultAndroidEventProcessorTest {
assertEquals("en_US", device.locale)
}
}

@Test
fun `Event sets InForeground to true if not in the background`() {
val sut = fixture.getSut(context)

AppState.getInstance().setInBackground(false)

assertNotNull(sut.process(SentryEvent(), Hint())) {
val app = it.contexts.app!!
assertTrue(app.inForeground!!)
}
}

@Test
fun `Event sets InForeground to false if in the background`() {
val sut = fixture.getSut(context)

AppState.getInstance().setInBackground(true)

assertNotNull(sut.process(SentryEvent(), Hint())) {
val app = it.contexts.app!!
assertFalse(app.inForeground!!)
}
}
}
6 changes: 6 additions & 0 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -2510,6 +2510,7 @@ public final class io/sentry/protocol/App : io/sentry/JsonSerializable, io/sentr
public fun getAppVersion ()Ljava/lang/String;
public fun getBuildType ()Ljava/lang/String;
public fun getDeviceAppHash ()Ljava/lang/String;
public fun getInForeground ()Ljava/lang/Boolean;
public fun getPermissions ()Ljava/util/Map;
public fun getUnknown ()Ljava/util/Map;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
Expand All @@ -2520,6 +2521,7 @@ public final class io/sentry/protocol/App : io/sentry/JsonSerializable, io/sentr
public fun setAppVersion (Ljava/lang/String;)V
public fun setBuildType (Ljava/lang/String;)V
public fun setDeviceAppHash (Ljava/lang/String;)V
public fun setInForeground (Ljava/lang/Boolean;)V
public fun setPermissions (Ljava/util/Map;)V
public fun setUnknown (Ljava/util/Map;)V
}
Expand All @@ -2539,6 +2541,7 @@ public final class io/sentry/protocol/App$JsonKeys {
public static final field APP_VERSION Ljava/lang/String;
public static final field BUILD_TYPE Ljava/lang/String;
public static final field DEVICE_APP_HASH Ljava/lang/String;
public static final field IN_FOREGROUND Ljava/lang/String;
public fun <init> ()V
}

Expand Down Expand Up @@ -3344,11 +3347,13 @@ public final class io/sentry/protocol/SentryThread : io/sentry/JsonSerializable,
public fun isCrashed ()Ljava/lang/Boolean;
public fun isCurrent ()Ljava/lang/Boolean;
public fun isDaemon ()Ljava/lang/Boolean;
public fun isMain ()Ljava/lang/Boolean;
public fun serialize (Lio/sentry/JsonObjectWriter;Lio/sentry/ILogger;)V
public fun setCrashed (Ljava/lang/Boolean;)V
public fun setCurrent (Ljava/lang/Boolean;)V
public fun setDaemon (Ljava/lang/Boolean;)V
public fun setId (Ljava/lang/Long;)V
public fun setMain (Ljava/lang/Boolean;)V
public fun setName (Ljava/lang/String;)V
public fun setPriority (Ljava/lang/Integer;)V
public fun setStacktrace (Lio/sentry/protocol/SentryStackTrace;)V
Expand All @@ -3367,6 +3372,7 @@ public final class io/sentry/protocol/SentryThread$JsonKeys {
public static final field CURRENT Ljava/lang/String;
public static final field DAEMON Ljava/lang/String;
public static final field ID Ljava/lang/String;
public static final field MAIN Ljava/lang/String;
public static final field NAME Ljava/lang/String;
public static final field PRIORITY Ljava/lang/String;
public static final field STACKTRACE Ljava/lang/String;
Expand Down
22 changes: 22 additions & 0 deletions sentry/src/main/java/io/sentry/protocol/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public final class App implements JsonUnknown, JsonSerializable {
private @Nullable String appBuild;
/** Application permissions in the form of "permission_name" : "granted|not_granted" */
private @Nullable Map<String, String> permissions;
/**
* A flag indicating whether the app is in foreground or not. An app is in foreground when it's
* visible to the user.
*/
private @Nullable Boolean inForeground;

public App() {}

Expand All @@ -50,6 +55,7 @@ public App() {}
this.buildType = app.buildType;
this.deviceAppHash = app.deviceAppHash;
this.permissions = CollectionUtils.newConcurrentHashMap(app.permissions);
this.inForeground = app.inForeground;
this.unknown = CollectionUtils.newConcurrentHashMap(app.unknown);
}

Expand Down Expand Up @@ -122,6 +128,15 @@ public void setPermissions(@Nullable Map<String, String> permissions) {
this.permissions = permissions;
}

@Nullable
public Boolean getInForeground() {
return inForeground;
}

public void setInForeground(final @Nullable Boolean inForeground) {
this.inForeground = inForeground;
}

// region json

@Nullable
Expand All @@ -144,6 +159,7 @@ public static final class JsonKeys {
public static final String APP_VERSION = "app_version";
public static final String APP_BUILD = "app_build";
public static final String APP_PERMISSIONS = "permissions";
public static final String IN_FOREGROUND = "in_foreground";
}

@Override
Expand Down Expand Up @@ -174,6 +190,9 @@ public void serialize(@NotNull JsonObjectWriter writer, @NotNull ILogger logger)
if (permissions != null && !permissions.isEmpty()) {
writer.name(JsonKeys.APP_PERMISSIONS).value(logger, permissions);
}
if (inForeground != null) {
writer.name(JsonKeys.IN_FOREGROUND).value(inForeground);
}
if (unknown != null) {
for (String key : unknown.keySet()) {
Object value = unknown.get(key);
Expand Down Expand Up @@ -220,6 +239,9 @@ public static final class Deserializer implements JsonDeserializer<App> {
CollectionUtils.newConcurrentHashMap(
(Map<String, String>) reader.nextObjectOrNull());
break;
case JsonKeys.IN_FOREGROUND:
app.inForeground = reader.nextBooleanOrNull();
break;
default:
if (unknown == null) {
unknown = new ConcurrentHashMap<>();
Expand Down
Loading

0 comments on commit a4ccef1

Please sign in to comment.