  With the continuous rise in the popularity of Android mobile devices,
automated testing of apps has become more important than ever. Android apps are
event-driven programs. Unfortunately, generating all possible types of events
by interacting with the app's interface is challenging for an automated testing
approach. Callback-driven testing eliminates the need for event generation by
directly invoking app callbacks. However, existing callback-driven testing
techniques assume prior knowledge of Android callbacks, and they rely on a
human expert, who is familiar with the Android API, to write stub code that
prepares callback arguments before invocation. Since the Android API is huge
and keeps evolving, prior techniques could only support a small fraction of
callbacks present in the Android framework.
  In this work, we introduce Columbus, a callback-driven testing technique that
employs two strategies to eliminate the need for human involvement: (i) it
automatically identifies callbacks by simultaneously analyzing both the Android
framework and the app under test, and (ii) it uses a combination of
under-constrained symbolic execution (primitive arguments), and type-guided
dynamic heap introspection (object arguments) to generate valid and effective
inputs. Lastly, Columbus integrates two novel feedback mechanisms -- data
dependency and crash-guidance, during testing to increase the likelihood of
triggering crashes, and maximizing coverage. In our evaluation, Columbus
outperforms state-of-the-art model-driven, checkpoint-based, and
callback-driven testing tools both in terms of crashes and coverage.
