Callbacks on Android
  • 18 Oct 2024
  • 14 Minutes to read
  • Dark
    Light

Callbacks on Android

  • Dark
    Light

Article summary

ExtendedObserver interface

The ExtendedObserver interface contains only one method: handleCallback(CallbackData data).

The CallbackData object contains all information supplied for a given callback.

CallbackData class

The CallbackData class serves as a base class for other classes that contain data for specific callbacks. These inherited classes reside in the no.promon.shield.callbacks package and have a ...Data suffix, for example RootingData or RepackagingData.

Each callback has a type, represented by enumCallbackType and is available via the CallbackData.getCallbackType() method call. Based on the return value of the CallbackData.getCallbackType() call, the callback handler can cast the CallbackData object to the correct descending type that contains the data for the callback.

If CallbackData.getCallbackType() returned CallbackType.ROOTING, the callback handler should cast the CallbackData object to the RootingData object and then, using methods of the RootingData class, retrieve information specific to the ROOTING callback.

Example code

Java

 

public class ExtendedObserverImplementation implements ExtendedObserver {
  public void handleCallback(CallbackData data) {
    switch (data.getCallbackType()) {
      case ROOTING: {
        RootingData callbackData = (RootingData) data;
        handleRootingCallback(
          callbackData.isDeviceCertainlyRooted(),
          callbackData.getRootingProbability());
        break;
      }
      case HOOKING_FRAMEWORKS: {
        HookingFrameworksData callbackData = (HookingFrameworksData) data;
        handleHookingFrameworksCallback(
          callbackData.areHookingFrameworksPresent(),
          callbackData.getLastUsedDetectionMethodCode());
        break;
      }
      ...
    }
  }
  ...
}
...
ExtendedObserver observer = new ExtendedObserverImplementation();
CallbackManager.addObserver(context, observer);

Kotlin

 

class ExtendedObserverImplementation : ExtendedObserver {
  override fun handleCallback(data: CallbackData) {
    when (data?.callbackType) {
      CallbackType.ROOTING -> {
        val callbackData = data as RootingData
        handleRootingCallback(
          callbackData.isDeviceCertainlyRooted,
          callbackData.rootingProbability
        )
      }
      CallbackType.HOOKING_FRAMEWORKS -> {
        val callbackData = data as HookingFrameworksData
        handleHookingFrameworksCallback(
          callbackData.areHookingFrameworksPresent()
          callbackData.getLastUsedDetectionMethodCode()
        )
      }
      ...
      else -> {
        ...
      }
    }
  }
  ...
}
...
val observer: ExtendedObserver = ExtendedObserverImplementation()
CallbackManager.addObserver (context, observer)

List of callback types: CallbackType enum

A list of callback types can be found in the CallbackType enum. Each callback type corresponds to its own callback data class, which extends the CallbackData class.

Callback types shows which callback type corresponds to which callback data class:

Callback types

Callback method

Description

Depends on enabling

ADB_STATUS

AdbStatusData

check ADB Status

DEBUGGER

DebuggerData

Check Debugger

DEVELOPER_OPTIONS

DeveloperOptionsData

check Developer Options

EMULATED_INPUT

EmulatedInputData

Check Emulated Input

EMULATOR

EmulatorData

Check Emulator

FILESYSTEM_SCANNING

FilesystemScanningData

Check RootingDeepScan, checkRooting

FILESYSTEM_WATCHING

FilesystemWatchingData

checkRooting

HOOKING_FRAMEWORKS

HookingFrameworksData

Check HookingFrameworks

KEYBOARD

KeyboardData

Check Trusted Keyboard

NATIVE_CODE_HOOKS

NativeCodeHooksData

Check NativeCodeHooks

PRIVATE_SPACE

PrivateSpaceData

Check Private Space

REPACKAGING

RepackagingData

Check Repackaging

ROOTING

RootingData

checkRooting

SCREEN_MIRRORING

ScreenMirroringData

check Screen Mirroring

SCREENREADER

ScreenreaderData

Check Trusted Screenreaders

TAPJACKING

TapjackingData

Check Tapjacking

TASK_HIJACKING

TaskHijackingData

N/A: requires the import of ShieldSDK-activity-guard.aar

UNTRUSTED_SOURCE_APP

UntrustedSourceAppData

check Untrusted Installer

VIRTUAL_SPACE_APP

VirtualSpaceAppData

Check App in Virtual Space

PRIVATE_SPACE

PrivateSpaceData

Check Private Space

Callback data classes

The ExtendedObserver.handleCallback() method is called after App Shielding has performed security checks, with a callback-specific CallbackData object (see Callback types).

Callback data classes

Callback method

Description

AdbStatusData

This class contains information about the detected Android Developer Bridge (ADB) status. If the boolean isAdbActive() return value is true, the device’s ADB is considered active.

DebuggerData

This class contains information about whether a Java debugger is attached to the host application. If the boolean isRunningUnderDebugger() method returns true, a Java debugger is attached.

If App Shielding is configured to block Java debuggers this callback is never called. Low-level debuggers, such as gdb are blocked altogether, and no callback will be called if anyone tries to attach such a debugger to the application.

DeveloperOptionsData

This class contains information about the Developer Options status. If the return value of boolean isDeveloperOptionsEnabled() is true, the device’s Developer Options are enabled.

EmulatedInputData

This class contains information about a detected emulated input. If the boolean isInputEmulated() return value is true, an emulated input was detected. The input can be both touch and swipe events.

EmulatorData

This class contains information about whether or not App Shielding detects that the application is executed inside an emulator. If the return value of boolean isRunningOnEmulator() is true, the application is running inside an emulator.

Release versions of App Shielding do not permit executing on emulators, so this callback can only be used when using debug versions of App Shielding on an emulator.

FilesystemScanningData

This class contains information about whether suspicious files have been detected in the file system.

The following are the public methods for this class:

  • boolean isSuidOrSgidDetected
    Indicates if a file with suid or sgid bit is detected.

  • boolean isSuDetected
    Indicates if su executable file is detected.

  • boolean isSuspiciousFileDetected
    Indicates if any suspicious file is detected, either a file with an suid or sgid bit, or a file which is su executable. In other words, isSuspiciousFileDetected() returns true if isSuidOrSgidDetected() or isSuDetected() (or both) return true.

The file system scanning callback is usually invoked 5-10 seconds after application startup because file system scanning takes time.

FilesystemWatchingData

This class contains information about suspicious activity on the file system. This check depends on root detection being enabled. Currently, the following scenarios are considered suspicious activity:

  • An Suid or sgid bit is set on an executable in one of the bin paths.

  • An su executable is copied into one of the bin paths.

The following public methods are available for this class:

  • String getSuspiciousFileName

    Returns name of the suspicious file.

  • boolean isSuidOrSgidDetected

    Indicates if the suspicious file has suid or sgid bit.

  • boolean isSuDetected

    Indicates if the suspicious file is su executable.

The file system watching callback is only invoked if suspicious activity happens on the file system during application runtime. If suspicious files are already present on the file system before the application starts, their presence will be reported via the file system scanning callback, not via the file system watching callback.

HookingFrameworksData

This class contains information about code hooking frameworks in the process.

The following public methods are available for this class:

  • boolean areHookingFrameworksPresent

    Returns true if code hooking frameworks are present.

  • int getLastUsedDetectionMethodCode

    Returns the last used detection method code. Provide this code to OneSpan if you are trying to diagnose a problem with hooking framework detection.

OneSpan recommends to configure App Shielding to exit the application if code hooking frameworks are detected. This callback should not be used to make security decisions because such frameworks can modify the behavior of the callback.

KeyboardData

This class contains information about whether the active keyboard on the system is trusted.

The following public methods are available for this class:

  • boolean isKeyboardUntrusted

    Returns true if the active keyboard is untrusted.

    App Shielding treats keyboards that are part of the original firmware as trusted. Otherwise, the signer of the keyboard is compared to a list of trusted signers that can be configured in the App Shielding configuration (see Additional trusted keyboard signatures in OneSpan Customer Portal).

  • String getKeyboardPackageName

    Returns the keyboard APK package name.

  • String getKeyboardVersionName
    Returns the keyboard APK package's human-readable version name, which is usually specified in AndroidManifest.xmlby the versionName attribute of the <manifest> tag.

  • String getKeyboardAppLabel
    Returns the keyboard app's human-readable name (i.e., label), which is usually specified in AndroidManifest.xml by the label attribute of the <application> tag.

  • String getKeyboardSignerName

    Returns the Common Name (CN) of the keyboard APK signer’s X.509 certificate subject. If it is impossible to determine the CN field, this method returns an empty string.

NativeCodeHooksData

This class contains information about whether native code hooks are present. If the boolean areNativeCodeHooksPresent() return value is true, native code hooks are present. If false, no native code hooks are detected.

PrivateSpaceData

Contains information about whether App Shielding detects that the application is executed inside aPrivate Space or Work Profile.

If the boolean isRunningInPrivateSpaceOrWorkProfile() method returns true, the application is running inside a Private Space or a Work Profile; the data does not specify which one.

RepackagingData

Provides a boolean that indicates whether the application has been repackaged. If the application is running in a simulator, this method is never called. If the boolean isRepackaged() return value is true, the application has been repackaged.

This callback is only triggered if the exitOnRepackaging option is set to false. exitOnRepackaging cannot be disabled in a release version of App Shielding.

RootingData

This class contains information about whether App Shielding has detected that the device is rooted or not.

The following public methods are available for this class:

  • boolean isDeviceCertainlyRooted()

    Indicates if the device is rooted or not. Returns true if App Shielding is certain that the device is rooted.

  • int getRootingProbability()

    Returns a percentage value that indicates the probability that a device is rooted, based on heuristic checks. A value of 0 indicates that the device is most likely not rooted, while a value of 100 indicates that the device is most likely rooted. This value is created independently of the value returned by isDeviceCertainlyRooted, so they are not connected in any way and might contradict each other in certain cases.

  • int getLastUsedDetectionMethodCode

    Returns the last used detection method code. Supply this code to OneSpan if you are trying to diagnose a problem with the rooting detection.

  • int getLastUsedHeuristicMethodCode()

    Returns the last used heuristic method code. Supply this code to OneSpan if you are trying to diagnose a problem with the rooting detection.

ScreenMirroringData

This class contains information about active screen mirrors. Such screen readers might include the device projecting the screen to a Chrome Cast device, MiraCast, or other type of screen casting device.

The following public methods are available for this class:

  • boolean isScreenMirroringDetected()

    Returns true if screen mirroring is detected.

  • boolean isScreenMirroringBlocked()

    Returns true if the screen mirroring is currently being blocked by App Shielding.

ScreenreaderData

This class contains information about whether an untrusted screen reader is active.

The following public methods are available for this class:

  • boolean isUntrustedScreenreaderPresent()

    Returns true if an active screen reader that is not included in the allowlist has been found. Trusted screen readers can be configured with the addTrustedScreenreaderSigner option.

  • int getUntrustedScreenreaderCount()

    Returns the number of untrusted active screen readers.

  • String getUntrustedScreenreaderPackageName(int index)

    Returns the package name of the untrusted screen reader APK with the specified index. The index must be in the range of 0 to getUntrustedScreenreaderCount() - 1. If no screen readers are active or the index is out of bounds, this method returns an empty string.

  • String getUntrustedScreenreaderVersionName(int index)

    Returns the human-readable version name with the specified index, which is usually specified in AndroidManifest.xml by the versionName attribute of the manifest tag. The index must be in the range of 0 to getUntrustedScreenreaderCount() - 1. If no screen readers are active or the index is out of bounds, this method returns an empty string.

  • String getUntrustedScreenreaderAppLabel(int index)

    Returns the human-readable name (label) of the untrusted screen reader APK with the specified index, which is usually specified in AndroidManifest.xml by the label attribute of the application tag. The index must be in the range of 0 to getUntrustedScreenreaderCount() - 1. If no screen readers are active or the index is out of bounds, this method returns an empty string.

  • String getUntrustedScreenreaderSignerName(int index)

    Returns Common Name (CN) of the signer’s X.509 certificate subject for the untrusted screen reader APK with the specified index. The index must be in the range of 0 to getUntrustedScreenreaderCount() - 1. If no screen readers are active or the index is out of bounds, this method returns an empty string.

  • String getUntrustedScreenreaderSignature(int index)

    Returns the screen reader signature of the untrusted screen reader APK with the specified index. The index must be in the range of 0 to getUntrustedScreenreaderCount() - 1. If no screen readers are active or the index is out of bounds, this method returns an empty string.

    If the app is running in a Private Space or Work Profile, you should expect ScreenreaderData callbacks with untrusted screen readers.

TapjackingData

Provides details regarding input events that are affected by the presence of an overlay. The inputs can be touch events or swipe events.

The following public method is available for this class:

  • isObscured()

    Returns true if an input event is obscured by a non-system overlay.

TaskHijackingData

This class contains information about a task that was hijacked by an external application targeting this app through taskAffinity.

The following public methods are available for this class:

  • ComponentName getOffendingAppActivity()

    Returns ComponentName (app-packageName + activity class name) of the app/activity that hijacked this app’s task.

  • String getOffendingTaskAffinity()

    Returns the taskAffinity set by the offending activity.

  • String getIntentData()

    Returns the intent used to start the task.

The task hijacking callback is only called if task hijacking protection is enabled by including the ShieldSDK-activity-guard package in the application.

UntrustedSourceAppData

This class contains information about detected untrusted source or sideloaded application installed on the device. If an untrusted application is installed or uninstalled from the device while the application is running, the observer is notified with updated callback data.

UntrustedSourceAppData returns a list of all untrusted applications installed to the device. If a new untrusted application is installed, the installed application will not necessarily be added as the last item on the untrusted applications list.

The following public methods are available for this class:

  • boolean isUntrustedSourceAppPresent()

    Returns true if there are one or more untrusted source applications installed on the device.

    App Shielding trusts all system applications. For any other application, App Shielding compares the signer of the installer package with an allowlist of trusted signers that may be configured in the App Shielding configuration by addTrustedInstallerSigner. In addition to this option, it is possible to allowlist a single application installed via untrusted app store, or sideloaded by addTrustedApplicationSigner

  • int getUntrustedSourceAppCount()

    Returns the number of applications that were sideloaded or installed via untrusted sources.

  • String getUntrustedSourceAppPackageName(int index)

    Returns the package name of the untrusted source application at the specified index.

  • String getUntrustedSourceAppVersionName(int index)

    Returns the APK package’s human-readable version name of the untrusted source app at the specified index, which is usually specified in AndroidManifest.xml by the versionName attribute of the <manifest> tag .

  • String getUntrustedSourceAppLabel(int index)

    Returns the human-readable name (i.e., label) of the untrusted source app at the specified index, which is usually specified in AndroidManifest.xml by the label attribute of the <application> tag.

  • String getUntrustedSourceAppSignerName(int index)

    Returns the Common Name (CN) of the APK signer’s X.509 certificate subject for the untrusted source app at the specified index. If it is not possible to determine the CN field, this method returns an empty string.

  • String getUntrustedSourceAppSignature(int index)

    Returns the APK signature of the untrusted source app APK at index. If it is not possible to determine the signature, this method returns an empty string.

The following methods return information about the corresponding installer for an untrusted source app:

  • String getUntrustedSourceAppInstallerPackageName(int index)

    Returns the package name of the installer of the untrusted source application at the given index.

  • String getUntrustedSourceAppInstallerSignerName(int index)

    Returns the Common Name (CN) of the installer APK signer’s X.509 certificate subject for the untrusted source app at the specified index. If it is not possible to determine the CN field, this method returns an empty string.

  • String getUntrustedSourceAppInstallerSignature(int index)

    Returns the installer APK signature of the untrusted source app at the provided index. If it is not possible to determine the signature, this method returns an empty string.

    If the installer is removed from the device, the affected apps are still marked as having an "untrusted source", but the getUntrustedSourceAppInstaller* methods will then return empty values for those installers.

VIRTUAL_SPACE_APP

This callback contains information about whether the application was launched via a virtual space app.

The following public methods are available for this class:

  • boolean isAppInVirtualSpace()

    Returns true if the application is launched via a virtual space app. Returns false if the application is not in a virtual space or is in the virtual space of any application included in the allowlist by addTrustedVirtualSpaceAppSigner.

  • String getVirtualSpaceAppPackageName()

    Returns the virtual space app’s APK package name. If the application is launched outside of a virtual space, this method returns an empty string.

  • String getVirtualSpaceAppVersionName()

    Returns the virtual space app’s APK package human- readable version name, which is usually specified in AndroidManifest.xml by the versionName attribute of the <manifest> tag. If the application is launched outside of a virtual space, this method returns an empty string.

  • String getVirtualSpaceAppAppLabel()

    Returns the virtual space app’s human-readable name (i.e., label), which is usually specified in AndroidManifest.xml by the label attribute of the <application> tag. If the application is launched outside of a virtual space, this method returns an empty string.

  • String getVirtualSpaceAppSignerName()

    Returns the Subject’s Common Name (CN) of the APK signer’s X.509 certificate subject of the virtual space app. If the application is launched outside of a virtual space, this method returns an empty string.

  • String getVirtualSpaceAppSignature()

    Returns the virtual space app’s signature. If the application is launched outside of a virtual space, this method returns an empty string.

Due to the limitations with some virtual spaces like Samsung Secure Folder and Xiaomi Dual Apps, the get methods return empty values regardless.

VirtualSpaceAppData

This callback contains information about whether the application was launched via a virtual space app.

The following public methods are available for this class:

  • boolean isAppInVirtualSpace()

    Returns true if the application is launched via a virtual space app. Returns false if the application is not in a virtual space or is in the virtual space of any application included in the allowlist by addTrustedVirtualSpaceAppSigner.

  • String getVirtualSpaceAppPackageName()

    Returns the virtual space app’s APK package name. If the application is launched outside of a virtual space, this method returns an empty string.

  • String getVirtualSpaceAppVersionName()

    Returns the virtual space app’s APK package human- readable version name, which is usually specified in AndroidManifest.xml by the versionName attribute of the <manifest> tag. If the application is launched outside of a virtual space, this method returns an empty string.

  • String getVirtualSpaceAppAppLabel()

    Returns the virtual space app’s human-readable name (i.e., label), which is usually specified in AndroidManifest.xml by the label attribute of the <application> tag. If the application is launched outside of a virtual space, this method returns an empty string.

  • String getVirtualSpaceAppSignerName()

    Returns the Subject’s Common Name (CN) of the APK signer’s X.509 certificate subject of the virtual space app. If the application is launched outside of a virtual space, this method returns an empty string.

  • String getVirtualSpaceAppSignature()

    Returns the virtual space app’s signature. If the application is launched outside of a virtual space, this method returns an empty string.

Due to the limitations with some virtual spaces like Samsung Secure Folder and Xiaomi Dual Apps, the get methods return empty values regardless.

The following callbacks can only be used when the app is shielded in Debug mode:

  • RepackagingData: In case of a repackaging attack, the application will exit immediately.

  • EmulatorData: If an emulator is detected, the application will exit immediately.

  • DebuggerData: Java debuggers are blocked by default. If blocking is not possible, the application will exit immediately. Low-level debuggers, such as gdb are simply blocked.                

  • NativeCodeHooksData: If a native code hook is detected, the application will exit immediately.

The anti-debugging feature is only operational when the App Shielding native library is loaded. However, only the Android OS code can be debugged during application startup, the application code cannot be debugged. After the library has been loaded, the debugger is killed.

Security and priority are equally important in App Shielding. The EXIT reaction is safer than a callback and has therefore precedence over a callback. To reach the place in the code with the callback, the EXIT reaction that corresponds to this detection should be turned off.


Was this article helpful?

Changing your password will log you out immediately. Use the new password to log back in.
First name must have atleast 2 characters. Numbers and special characters are not allowed.
Last name must have atleast 1 characters. Numbers and special characters are not allowed.
Enter a valid email
Enter a valid password
Your profile has been successfully updated.
ESC

Ozzy, our interactive help assistant