Repository navigation
Cancellation and logging
AndroSpecter is a library: the calling application owns cancellation requests, deadlines, log configuration, help output, and process exit codes. The current 2.0.0 API does not call System.exit from TimeOut or command-line parsing.
This page describes 2.0.0 on JDK 17, with Soot 4.7.1 and FlowDroid 2.15.1. See Getting started for installation and analysis sessions for opening and closing an APK analysis.
A CancellationSource provides a token to the analysis. Deadline.after(...) schedules a callback immediately when created; the callback below requests cancellation after two minutes. Closing the deadline disarms a pending callback. Neither object forcibly stops the analysis thread.
This complete utility class accepts a readable APK, the Android SDK platforms directory, and a package name without a trailing dot:
import com.jordansamhi.androspecter.analysis.AndroidAnalysis;
import com.jordansamhi.androspecter.execution.CancellationSource;
import com.jordansamhi.androspecter.execution.Deadline;
import com.jordansamhi.androspecter.inspection.Inspection;
import com.jordansamhi.androspecter.inspection.LibraryFilter;
import java.nio.file.Path;
import java.time.Duration;
import java.util.concurrent.CancellationException;
public final class CancellationExample {
/**
* Counts selected invocation sites until inspection finishes or cancellation is observed.
* @param apk readable APK file
* @param platforms Android SDK platforms directory
* @param packageName application package and subpackages to inspect
*/
public static void inspect(Path apk, Path platforms, String packageName) {
long[] calls = {0};
LibraryFilter scope = LibraryFilter.packages(packageName);
try (CancellationSource source = new CancellationSource();
Deadline deadline = Deadline.after(Duration.ofMinutes(2), source::cancel);
AndroidAnalysis analysis = AndroidAnalysis.builder(apk, platforms)
.cancellationToken(source.token())
.callbackTimeout(Duration.ofSeconds(30))
.taintTimeout(Duration.ofMinutes(1))
.pathTimeout(Duration.ofSeconds(20))
.open()) {
analysis.inspect(Inspection.builder()
.classes(clazz -> clazz.isApplicationClass() && scope.test(clazz))
.onInvoke((caller, statement, invocation) -> calls[0]++)
.build());
System.out.println("Invocation sites: " + calls[0]);
} catch (CancellationException ex) {
System.out.println("Cancelled; visited " + calls[0] + " invocation sites");
}
}
}Only opening and inspection execute here. The taint and path limits configure a later taint run; setting them does not run taint analysis. Resource closure happens in reverse declaration order, so the analysis closes on its owning thread before the source is disposed.
The runnable com.jordansamhi.androspecter.examples.CancelAnalysis example accepts <apk> <platforms> <package-prefix> <seconds>, where seconds is a positive whole number. See the examples README for build and launch commands.
-
source.cancel()is thread-safe, permanently marks the token cancelled, and invokes registered callbacks synchronously on the cancelling thread. It returnstrueonly for the first request. Callbacks should return promptly. - Another thread may call
source.cancel(). It must not call live analysis methods oranalysis.close(); those belong to the analysis's creating thread. -
source.close()also requests cancellation. In contrast,deadline.close()only disarms the timer and does not cancel the operation. -
token.throwIfCancellationRequested()checks the token and the calling thread's interrupt flag, throwingCancellationExceptionwithout clearing that flag. Custom transformations should check their context at suitable checkpoints. - Inspection and transformation boundaries check the context; checks also surround user predicates and callbacks. A long-running callback or backend phase must return or cooperate before the next check can run.
- FlowDroid receives a best-effort data-flow abort request. Callback and call-graph construction are not forcibly interrupted. Keep the session open until the running operation returns. A deadline is not a hard wall-clock bound.
Opening, inspection, and graph access report observed cancellation by throwing CancellationException. analysis.analyzeTaint(...) instead returns a taint result with status CANCELLED and any available findings. Lifecycle errors such as using a closed session still throw. Cancelled or timed-out findings must not be treated as a completed analysis.
| Builder setting | Scope |
|---|---|
callbackTimeout(Duration) |
FlowDroid DEFAULT callback analysis; expiration can leave a partial callback/call graph; ignored by FAST in FlowDroid 2.15.1 |
taintTimeout(Duration) |
Data-flow phase |
pathTimeout(Duration) |
Path reconstruction; flows may exist without reconstructed paths |
Zero disables the relevant phase limit. Positive durations round up to whole seconds; negative durations and values beyond the supported range are rejected. These limits are independent and do not add up to an enforced deadline for the complete operation.
Deadline.after(Duration.ZERO, action) schedules an immediate callback. This differs from legacy new TimeOut(0), which means 60 seconds. See TimeOut for that adapter's one-shot behavior.
AndroSpecter depends on slf4j-api 2.0.17 and does not install a runtime logging provider or global configuration. Add one provider to the calling application's dependencies. For a simple console setup:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.17</version>
<scope>runtime</scope>
</dependency>Avoid adding a second provider when the application already has one. The provider controls destinations and levels. AndroSpecter's test-scoped provider is not an application runtime dependency.
Use SLF4J directly for application logs, or the Writer compatibility facade. Writer no longer writes decorated console output itself. Its error, warning, and information methods map to SLF4J levels; they do not choose an exit status or throw merely because a message is an error.
Analysis logs and injected APK probes are separate: instrumentation inserts calls to android.util.Log.d for execution inside an instrumented app. An SLF4J provider in the analysis application does not execute or collect those Android probes.
CommandLineOptions returns immutable parse results. The caller checks helpRequested(), decides where to print helpText(), catches ValidationException, and chooses its executable's exit behavior. Parsing does not print help or terminate the JVM. AndroSpecter's library artifact is not a command-line analyzer; runnable examples supply their own entry points.
- Analysis sessions
- APK metadata
- Call graphs and inspection
- Graph export and comparison
- Taint analysis
- Instrumentation
- Cancellation and logging
- Migration and troubleshooting
- Publishing releases