Automated Repair of Resource Leaks in Android Applications

Resource leaks -- a program does not release resources it previously acquired -- are a common kind of bug in Android applications. Even with the help of existing techniques to automatically detect leaks, writing a leak-free program remains tricky. One of the reasons is Android's event-driven programming model, which complicates the understanding of an application's overall control flow. In this paper, we present PlumbDroid: a technique to automatically detect and fix resource leaks in Android applications. PlumbDroid uses static analysis to find execution traces that may leak a resource. The information built for detection also undergirds automatically building a fix -- consisting of release operations performed at appropriate locations -- that removes the leak and does not otherwise affect the application's usage of the resource. An empirical evaluation on resource leaks from the DroidLeaks curated collection demonstrates that PlumbDroid's approach is scalable, precise, and produces correct fixes for a variety of resource leak bugs: PlumbDroid automatically found and repaired 50 leaks that affect 9 widely used resources of the Android system, including all those collected by DroidLeaks for those resources; on average, it took just 2 minutes to detect and repair a leak. PlumbDroid also compares favorably to Relda2/RelFix -- the only other fully automated approach to repair Android resource leaks -- since it usually detects more leaks with higher precision and producing smaller fixes. These results indicate that PlumbDroid can provide valuable support to enhance the quality of Android applications in practice.


Introduction
The programming model of the Android operating system makes its mobile applications ("apps") prone to bugs that are due to incorrect usage of shared resources.An app's implementation typically runs from several entry points, which are activated by callbacks of the Android system in response to events triggered by the mobile device's user (for example, switching apps) or other changes in the environment (for example, losing network connectivity).Correctly managing shared resources is tricky in such an event-driven environment, since an app's overall execution flow is not apparent from the control-flow structure of its source code.This explains why resource leaks-bugs that occur when a shared resource is not correctly released or released too late-are one of the most common kind of performance bugs in Android apps [44,30,38], where they often result in buggy behavior that ultimately degrades an app's responsiveness and usability.
Motivated by their prevalence and negative impact, research in the last few years (which we summarize in Section 5) has developed numerous techniques to detect resource leaks using dynamic analysis [44,13], static analysis [53,55,28], or a combination of both [12].Automated detection is very useful to help developers in debugging, but the very same characteristics of Android programming that make apps prone to having resource leaks also complicate the job of coming up with leak repairs that are correct in all conditions.
To address these difficulties, we present a technique to detect and fix resource leaks in Android apps completely automatically.Our technique, called PLUMBDROID and described in Section 3, is based on static analysis and can build fixes that are correct (they eradicate the detected leaks for a certain resource) and "safe" (they do not introduce conflicts with the rest of the app's usage of the resource, and follow Android's recommendations for resource management [4]).
PLUMBDROID's analysis is scalable because it is based on a succinct abstraction of an app's control-flow graph called resource-flow graph.Paths on an app's resourceflow graph correspond to all its possible usage of resources.Avoiding leaks entails matching each acquisition of a resource with a corresponding release operation.PLUMB-DROID supports the most general case of reentrant resources (which can be acquired multiple times, typically implemented with reference counting in Android): absence of leaks is a context-free property [46]; and leak detection amounts to checking whether every path on the resource-flow graph belongs to the context-free language of leak-free sequences.PLUMBDROID's leak model is more general than most other leak detection techniques'-which are typically limited to non-reentrant resources (see Table 8).
The information provided by our leak detection algorithm also supports the automatic generation of fixes that remove leaks.PLUMBDROID builds fixes that are correct by construction; a final validation step reruns the leak detection algorithm augmented with the property that the new release operations introduced by the fix do not interfere with the existing resource usages.Fixes that pass validation are thus correct and "safe" in this sense.
We implemented our technique PLUMBDROID in a tool, also called PLUMBDROID, that works on Android bytecode.PLUMBDROID can be configured to work on any Android resource API; we equipped it with the information about acquire and release operations of 9 widely used Android resources (including Camera and WifiManager), so that it can automatically repair leaks of those resources.
The current implementation of PLUMBDROID is not equipped with any aliasing analysis technique; therefore, it may incur a large number of false positives when applied to apps that use resources under lots of different aliases.We found that different Android resources have distinct usage patterns: some, such as database cursors, are frequently used under many aliases; others, such as the camera or the Wi-Fi adapter, are not.PLUMBDROID's current implementation is geared towards analyzing the latter kind of resources, which we call non-aliasing resources and are the main target of our experiments with PLUMBDROID.
We evaluated PLUMBDROID's performance empirically on leaks of 9 non-aliasing resources in 17 Android apps from the curated collection DroidLeaks [29].These experiments, described in Section 4, confirm that PLUMBDROID is a scalable automated leak repair technique (around 2 minutes on average to find and repair a leak) that consistently produces correct and safe fixes for a variety of Android resources (including all 26 leaks in DROIDLEAKS affecting the 9 analyzed resources).
We also experimentally compared PLUMBDROID with Relda2/RelFix [55,28]-the only other fully automated approach to repair Android resource leaks that has been developed so far-by running the former on the same apps used in the latter's evaluation.The comparison, also described in Section 4, indicates that, on non-aliasing resources, PLUMBDROID detects more true leaks (79 vs. 53) with a higher average precision (89% vs. 55%) than Relda2/RelFix, and produces fixes that are one order of magnitude smaller.
PLUMBDROID's novelty and effectiveness lie in how it combines and fine-tunes existing analysis techniques to the usual characteristics of Android resource usage.1. PLUMBDROID's fine-grained, yet succinct, abstract model of resource usage supports a sound static analysis with high precision; 2. PLUMBDROID's fix generation process follows Android's guidelines about the program locations where each resource should be released; 3. PLUMBDROID's validation step further guarantees that the fixes that it automatically generates are suitable and correct.
In summary, this paper makes the following contributions: • It introduces PLUMBDROID: a fully automated technique based on static analysis for the detection and repair of Android resource leaks.
• It evaluates the performance of PLUMBDROID on apps in DROIDLEAKS, showing that it achieves high precision and recall, and scalable performance.
• It experimentally compares PLUMBDROID to the other approach Relda2/RelFix on the same apps used in the latter's evaluation, showing that it generally achieves higher precision and recall.
• For reproducibility, the implementation of PLUMBDROID, as well as the details of its experimental evaluation (including the produced fixes), are publicly available in a replication package: As its name suggests, this class implements the activity-a kind of task in Android parlance-triggered when the user wants to view an image that she downloaded from some chat room.When the activity starts (method onCreate), the class acquires permission to use the system's media player by creating an object of class MediaPlayer on line 7.Other parts of the activity's implementation (not shown here) use player to interact with the media player as needed.
When the user performs certain actions-for example, she flips the phone's screenthe Android system executes the activity's method onPause, so that the app has a chance to appropriately react to such changes in the environment.Unfortunately, the implementation of onPause in Figure 1 does not release the media player, even though the app will be unable to use it while paused [40].Instead, it just acquires a new handle to the resource when it resumes.This causes a resource leak: the acquired resource MediaPlayer is not appropriately released.Concretely, if the user flips the phone back and forth-thus generating a long sequence of unnecessary new acquires-the leak will result in wasting system resources and possibly in an overall performance loss.
Such resource leaks can be tricky for programmers to avoid.Even in this simple example, it is not immediately obvious that onPause may execute after onCreate, since this requires a clear picture of Android's reactive control flow.Furthermore, a developer may incorrectly assume that calling the implementation of onPause in Android's base class Activity (with super.onPause())takes care of releasing the held resources.However, Activity.onPausecannot know about the resources that have been specifically allocated by the app's implementation; in particular, it does not release MediaPlayer() instance player.
PLUMBDROID can automatically analyze the implementation of IRCCloud looking for leaks such as the one highlighted in Figure 1.PLUMBDROID generates an abstraction In the ANALYSIS step, PLUMBDROID searches the graph abstraction for resource leaks: paths where a resource k is acquired (a k ) but not eventually released.In the FIXING step, PLUMBDROID injects the missing release operations r k where needed along the leaking path.In the final VALIDATION step, PLUMBDROID abstracts and analyzes the code after fixing, so as to ensure that the fix does not introduce unintended interactions that cause new resource-usage related problems.
of the whole app's control-flow that considers all possible user interactions that may result in leaks.For each detected leak, PLUMBDROID builds a fix by adding suitable release statements.
For Figure 1's example, PLUMBDROID builds a succinct fix at line 14 consisting of the conditional release operation if (player != null) player.release().PLUMB-DROID also checks that the fix is correct (it removes the leak) and "safe" (it only releases the resource after the app no longer uses it).Systematically running PLUMBDROID on Android apps can detect and fix many such resource leaks completely automatically.

How PLUMBDROID Works
Figure 2 gives a high-level overview of how PLUMBDROID works.Each run of PLUMBDROID analyzes an app for leaks of resources from a specific Android APIconsisting of acquire and release operations-modeled as described in Section 3.1.
The key abstraction used by PLUMBDROID is the resource-flow graph: a kind of control-flow graph that captures the information about possible sequences of acquire and release operations.Section 3.2.1 describes how PLUMBDROID builds the resourceflow graph for each procedure individually.
A resource leak is an execution path where some acquire operation is not eventually followed by a matching release operation.In general, absence of leaks (leak freedom) is a context-free property [46] since there are resources-such as wait locks-that may be acquired and released multiple times (they are reentrant). 1 Therefore, finding a resource leak is equivalent to analyzing context-free patterns on the resource-flow graph.PLUMBDROID's detection of resource leaks at the intra-procedural level is based on this equivalence, which Section 3.2.2describes in detail.
Android apps architecture.An Android application consists of a collection of standard components that have to follow a particular programming model [9].Each component type-such as activities, services, and content providers-has an associated callback graph, which constrains the order in which user-defined procedures are executed.As shown by the example of Figure 3, the states of a callback graph are macro-state of the app (such as Starting, Running, and Closed), connected by edges associated with callback functions (such as onStart, onPause, and onStop).An app's implementation defines procedures that implement the appropriate callback functions of each component (as in the excerpt of Figure 1).
Following this programming model, the overall control-flow of an Android app is not explicit from the app's implementation.Rather, the Android system triggers callbacks according to the transitions that are taken at run time (which, in turn, depend on the events that occur).PLUMBDROID deals with this implicit execution flow in two steps.First (Section 3.3.1),it defines an explicit inter-procedural analysis: it assumes that the inter-procedural execution order is known, and combines the intra-procedural analysis of different procedures to detect leaks across procedure boundaries.Second (Section 3.3.2),it unrolls the callback graph to enumerate sequences of callbacks that may occur when the app is running, and applies the explicit inter-procedural analysis to these sequences.
Fix generation.PLUMBDROID's analysis stage extracts detailed information that is useful not only to detect leaks but also to generate fixes that avoid the leaks.As we will describe in Section 3.4, PLUMBDROID builds fixes by adding a release of every leaked resource as early as possible along each leaking execution path.
PLUMBDROID's fixes are correct by construction: they release previously acquired resources in a way that guarantees that the previously detected leaks no longer occur.However, it might still happen that a fix releases a resource that is used later by the app-thus introducing a use-after-release error.In order to rule this out, PLUMBDROID also runs a final validation step which reruns the leak analysis on the patched program.If validation fails, it means that the fix should not be deployed as is; instead, the programmer should modify it in a way that makes it consistent with the rest of the app's behavior.Our experiments with PLUMBDROID (in particular in Section 4.2.1)indicate that validation is nearly always successful; even it fails, it is usually clear how to reconcile the fix with the app's behavior.

Resources
A PLUMBDROID analysis targets a specific Android API, which we model as a resource list L representing acquire and release operations of the API as a list of pairs (a 1 , r 1 ) (a 2 , r 2 ) . ... A pair (a k , r k ) denotes an operation a k that acquires a certain resource together with another operation r k that releases the same resource acquired by a k .The same operation may appear in multiple pairs, corresponding to all legal ways of acquiring and then releasing it.For simplicity, we sometimes use L to refer to the whole API that L represents.For example, resource MediaPlayer can be acquired and released with (new, release)-used in Figure 1.

Intra-Procedural Analysis
In the intra-procedural analysis, PLUMBDROID builds a resource-flow graph for every procedure in the app under analysis.In the example of Figure 1, it builds one such graph for every callback function, and for all methods called within those functions.

Resource-Flow Graphs
PLUMBDROID's analysis works on a modified kind of control-flow graph called resource-flow graph (RFG).The control-flow graphs of real-world apps are large and complex, but only a small subset of their blocks typically involve accessing resources.Resource-flow graphs abstract the control flow by only retaining information that is relevant for detecting resource leaks. 2 procedure's resource-flow graph R abstracts the procedure's control-flow graph C in two steps.First, it builds a resource path graph p for every basic block in C-as described by Algorithm 1.Then, it builds the resource-flow graph R by connecting the resource path graphs according to the control-flow structure-as described by Algorithm 2.
Resource path graph.A basic block corresponds to a sequence of statements without internal branching.Algorithm 1 builds the resource path graph p for any basic block b.It creates a node n in p for each statement s in b that is relevant to how L's resources are used: a resource is acquired or released, or execution terminates with a return (which may introduce a leak).Nodes in the resource path graph also keep track of when any other operation is performed, because this information is needed for inter-procedural analysis (as we detail in Section 3. analysis is sufficient whenever a procedure doesn't have any transfer nodes.Graph p connects the nodes in the same sequential order as statements in b.When a block b does not include any operations that are relevant for resource usage, its resource path graph p consists of a single trivial node, whose only role is to preserve the overall control-flow structure in the resource-flow graph.Since b is a basic block-that is, it has no branching-p is always a path graph-that is a linear sequence of nodes, each connected to its unique successor, starting from an entry node and ending in an exit node. Resource-flow graph.Algorithm 2 builds the resource-flow graph R of controlflow graph C-corresponding to a single procedure.First, it computes a path graph p(b) for every (basic) block b in C.Then, it connects the various path graphs following the control-flow graph's edge structure: it initializes R with an entry node s and connects it to the entry node of p(c 0 )-the path graph of C'e entry block; for every edge b 1 → b 2 connecting block b 1 to block b 2 in C, it connects the exit node of p(b 1 ) to the entry node of p(b 2 ).Since every executable block b ∈ C is connected to C's entry block c 0 , and c 0 's path graph is connected to R's entry node s, R is a connected graph that includes one path subgraph for every executable block in the control-flow graph C. Also, R has a single entry node s and a single exit node f .
Given that R's structure matches C's, if there is a path in C that leaks some of L's resources, there is also a path in R that exposes the same leak, and vice versa.Thus, we use the expression "R has leaks/is free from leaks in L" to mean "the procedure modeled by C has leaks/is free from leaks of resources in the API modeled by L".
Figure 4 shows the (simplified) resource-flow graphs of methods onCreate and onPause from Figure 1's example.Since each method consists of a single basic block, the resource-flow graphs are path graphs (without branching).

Context-Free Emptiness: Overview
Given a resource-flow graph R-abstracting a procedure P of the app under analysis-and a resource list L, P is free from leaks of resources in L if and only if every execution trace in R consistently acquires and releases resources in L. We express this check as a formal-language inclusion problem-à la automata-based modelchecking [48]-as follows (see Figure 5 for a graphical illustration): 1. We define a resource automaton A L that accepts sequences of operations in L that are free from leaks.Since leak freedom is a (deterministic) context-free property, the resource automaton is a (deterministic) pushdown automaton. 3Resource automata are described in Section 3.2.3.) 2. We define the complement automaton A L of A L , which accepts precisely all sequences of operations in L that leak.Since A L is a deterministic push-down automaton, A L is too a deterministic push-down automaton.
(Complement automata are described in Section 3.2.4.) 3. We define a flow automaton A R that captures all possible paths through the nodes of resource-flow graph R. Since A R is built directly from R, it is a (deterministic) finite-state automaton.The intra-procedural analysis described in Section 3.2 builds a resource-flow graph (RFG) for each procedure onCreate and onPause independently.As described in Section 3.3, the inter-procedural analysis considers, among others, the sequence of callback functions onCreate(); onStart(); onResume(); onPause(); since onStart() and onResume() do nothing in this example, this corresponds to connecting onCreate's exit to onPause's entry.The inter-procedural analysis thus finds a leaking path (in orange), where acquire operation new is not matched by any release operation.Fixing (Section 3.4) modifies the app by adding a suitable release operation player.release()(in green), which completely removes the leak.
A L : leak-free A L : leaking A R : procedure's resource usages A X : leaking usages Figure 5: A graphical display of PLUMBDROID's intra-procedural leak detection.The resource automaton AL captures all leak-free sequences; its complement AL captures all leaking sequences.The flow automaton AR captures all sequences of resource usages that may happen when the procedure under analysis runs.The intersection automaton A X captures the intersection of the violet and orange areas (outlined in dotted white), which marks the procedure's resource usage sequences that are leaking.If this area is empty, we conclude that the procedure is leak free.
(Flow automata are described in Section 3.2.5.) 4. We define the intersection automaton A X = A L × A R that accepts all possible paths in R that introduce a leak in resource L.
(Intersection automata are described in Section 3.2.6.) 5. We check if the intersection automaton accepts no inputs (the "empty language").If this is the case, it means that R cannot leak; otherwise, we found a leaking trace.
(Emptiness checking is described in Section 3.2.7.) The following subsections present these steps in detail.

Resource Automata
Given a resource list L = {(a 1 , r 1 ) (a 2 , r 2 ) . . .(a n , r n )}, the resource automaton A L is a deterministic pushdown automaton4 that accepts all strings that begin with a start character s, end with a final character f , and include all sequences of the characters a 1 , r 1 , a 2 , r 2 , . . ., a n , r n that encode all leak-free sequences of acquire and release operations.
More precisely, A L is a deterministic pushdown automaton if the resource modeled by L is a reentrant, and hence it can be acquired multiple times.If the resource modeled by L is not reentrant, A L is an ordinary finite state automaton (a simpler subclass of pushdown automata).In the remainder of this section, we recall the definitions of deterministic pushdown automata and finite-state automata, and we show the example of resource automaton of a reentrant resource, as well as one of a non-reentrant resource.
Pushdown automata.Pushdown automata [46] are finite-state automata equipped with an unbounded memory that is manipulated as a stack.For leak detection, we only need deterministic pushdown automata, where the input symbol uniquely determines the transition to be taken in each state.

Definition 1 (Deterministic pushdown automaton). A deterministic pushdown automaton
A is a tuple Σ, Q, I, Γ, δ, F , where: 1. Σ is the input alphabet; 2. Q is the set of control states; 3. I ⊆ Q and F ⊆ Q are the sets of initial and final states; 4. Γ is the stack alphabet, which includes a special "empty stack" symbol ⊥; 5. and the transition function.An automaton's computation starts in an initial state with an empty stack ⊥.When the automaton is in state q 1 with stack top symbol γ and input σ, if δ(q 1 , σ, γ) = (q 2 , G) is defined, it moves to state q 2 and replaces symbol γ on the stack with string G. L(A) ⊆ Σ * denotes the set of all input strings s accepted by A, that is such that A can go from one of its initial states to one of its final states by inputting s.

Reentrant resources.
Consider a reentrant resource with resource list L = {(a 1 , r 1 ) (a 2 , r 2 ) . . .(a n , r n )}.The resource automaton A L is a deterministic pushdown automaton that operates as follows.When A L inputs an acquire operation a k , it pushes it on to the stack; when it inputs a release operation r k , if the symbol on top of the stack is some a k such that (a k , r k ) ∈ L, it pops a k -meaning that the release matches the most recent acquire: since all operations in L correspond to the same resource, any release has to refer to the latest acquire.Finally, A L accepts the input if it ends up with an empty stack.
Example 1 (Resource automaton for WifiLock).Let's illustrate this construction in detail for the case of resource WifiLock with L W = {(acquire, release)} that is reentrant (see Table 1).Pushdown automaton A L W in Figure 6a accepts all strings over alphabet Σ L W = {s, f, acquire, release} of the form s B f where B is a string B ∈ {acquire, release} * is any balanced sequence of acquire and release-that is, a leak-free sequence.
Finite-state automata.Finite-state automata can be seen as a special case of pushdown automata without stack.
Definition 2 (Finite-state automaton).A finite-state automaton A is a five-element tuple Σ, Q, I, δ, F , where: 1. Σ is the input alphabet; 2. Q is the set of control states; 3. I ⊆ Q and F ⊆ Q are the sets of initial and final states; 4. and δ ⊆ Q × Σ × Q is the transition relation.An automaton's computation starts in an initial state.When the automaton is in state q 1 with input σ, if q 2 ∈ δ(q 1 , σ), it may move to state q 2 .L(A) ⊆ Σ * denotes the set of all input strings s accepted by A, that is such that A can go from one of its initial states to one of its final states by inputting s.
A finite-state automaton is deterministic when its transition relation δ is actually a function: the input uniquely determines the next state.
Non-reentrant resources.Consider a non-reentrant resource with resource list L = {(a 1 , r 1 ) (a 2 , r 2 ) . . .(a n , r n )}.The resource automaton A L is a finite-state automaton that operates as follows.When A L inputs an acquire operation a k , it moves to a new fresh state that is not final; the only valid transitions out of this state correspond to release operations r k such that (a k , r k ) ∈ L. Thus, A L accepts the input only if every acquire operation is immediately followed by a matching release operation.
Example 2 (Resource automaton for MediaPlayer).Resource MediaPlayer (used in the example of Section 2) is instead not reentrant (see Table 1), and offers operations 6b accepts all strings over alphabet Σ L M = {s, f, new, release, start, stop} of the form s (new release | start stop) * f , where each acquire operation is immediately followed by the matching release operation-that is, all leak-free sequences.

Complement Automata
Deterministic pushdown automata are a strict subclass of (nondeterministic) pushdown automata [1].Unlike general pushdown automata, deterministic pushdown automata are closed under complement.That is, given any deterministic pushdown automaton A, we can always build the complement A: a deterministic pushdown automaton that accepts precisely the inputs that A rejects and vice versa.For brevity, we do not repeat the classic construction of complement automata [46] The key idea is to switch final and non-final states, so that every computation that ends in a final state in A will be rejected in A and vice versa.Since finite-state automata are a subclass of deterministic pushdown automata, they are closed under complement too.
For our purposes, we need a slightly different complement automaton: one that accepts all sequences that begin with s, end with f , and include any leaking sequence of acquire and release in between these markers.For example, the automaton on the left in Figure 7 is the complement of MediaPlayer's resource automaton in Figure 6b that PLUMBDROID builds: it only accepts sequences that terminate with an f when there is a pending acquired resource before it's released.

Flow Automata
Given a resource-flow graph R = V, E , the flow automaton A R is a deterministic finite-state automaton that accepts precisely the language L(R) of all paths π through R such that π starts in R's entry node s and ends in R's exit node f .

More precisely, the flow automaton
are all acquire and release operations, plus symbols s and f ; 2. Q R = V ∪ {e} are all nodes of R plus a fresh exit node e; 3. I R = {s} is the unique entry node of R, and F R = {e} is the new unique exit node; 4. the transition relation δ R derives from R's edges: for every edge m → n in R, n ∈ δ R (m, type(m)) is a transition from state m to state n that reads input symbol type(m) corresponding to the type of node m (start, acquire, or release); plus a transition from R's exit node to the new exit node e reading f .Without loss of generality, we can assume that A R is deterministic, since finite-state automata are closed under determinization [46].That is, even if the construction above gives a nondeterministic finite-state automaton A R , we can always build an equivalent deterministic variant of it that accepts precisely the same inputs.
The middle automaton in Figure 7 is the flow automaton A R of onCreate in Figure 1's running example: it is isomorphic to onCreate's resource-flow graph (left in Figure 4) except for an additional final node e that follows f .

Intersection Automata
Given (the complement of) a resource automaton A L and flow automaton A R , the intersection automaton A X = A L × A R is a deterministic pushdown automaton that accepts precisely the intersection language L(A L ) ∩ L(A R ), that is the inputs accepted by both the complement automaton A L and the flow automaton A R .Therefore, A X precisely captures all sequences of acquire and release operations that may occur in R (that is, they are in L(A R )) and that leak some resource in L (that is, they are in L(A L ) = L(A L ) and thus are rejected by A L ).
More precisely, the intersection automaton A X is a deterministic pushdown automaton Σ X , Q X , I X , Γ X , δ X , F X , where: 1. Σ X = Σ L is the usual alphabet of all acquire and release operations, plus symbols s and f ; 2.
, σ, γ) that manipulates the stack as in A L 's transition.Since both A R and A L are deterministic, so is A X .
The rightmost automaton in Figure 7 is the intersection automaton of Figure 1's running example.Since the flow automaton A R is just a single path, it is identical to its intersection with A L M , which accepts the single leaking path.

Emptiness Checking
In the last step of its intra-procedural leak detection, PLUMBDROID has built the intersection automaton A X : a deterministic pushdown automaton that accepts all sequences of operations on resources L that may occur in the piece of code P corresponding to R and that leak some resource.In other words, R is free from leaks in L if and only if the intersection automaton A X accepts the empty language-that is, no inputs at all.
It is another classic result of automata theory that checking whether any pushdown automaton accepts the empty language (that is, it accepts no inputs) is decidable in polynomial time [1].
PLUMBDROID applies this classic decision procedure to determine whether A X accepts the empty language.If it does, then procedure P is leak free; otherwise, we found a trace of P that leaks.

Inter-Procedural Analysis
PLUMBDROID lifts the intra-procedural analysis to a whole app by analyzing all possible calls between procedures.The analysis of a given sequence of procedure calls combines the results of intra-procedural analysis as described in Section 3.3.1.Since in Android system callbacks determine the overall execution order of an app, Section 3.3.2explains how PLUMBDROID unrolls the callback graph to enumerate possible sequences of procedure calls-which are analyzed as if they were an explicit call sequence.
Algorithm 3: Algorithm AllCalls which computes inter-procedural resource-flow paths accepted by "leaking" pushdown automaton A L .Function LeakingPaths performs the intra-procedural detection of leaking paths described in Section 3.2.2.

Explicit Call Sequences
As it is customary, PLUMBDROID models calls between procedures with a call graph C: every node v in C is one of the procedures that make the app under analysis; and an edge u → v in C means that u calls v directly.In our analysis, a call graph may have multiple entry nodes, since Android applications have multiple entry points.
PLUMBDROID follows Algorithm 3 to perform inter-procedural analysis based on the call graph.First of all, we use topological sort (line 1) to rank C's nodes in an order that is consistent with the call order encoded by C's edges: if a node P has lower rank than a node Q it means that P does not call Q. Topological sort is applicable only if C is acyclic, that is there are no circular calls between procedures.If it detects a cycle, PLUMBDROID's implementation issues a warning and then breaks the cycle somewhere.As we discuss in Section 3.6 and Section 4, the restriction to acyclic call graphs seems minor in practice since all apps we analyzed had acyclic call graphs.
Once nodes in C are ranked according to their call dependencies, Algorithm 3 processes each of them starting from those corresponding to procedures that do not call any other procedures (line 4).The resource-flow graph of such procedures doesn't have any transfer nodes, and hence it can be completely analyzed using intra-procedural analysis.
Function LeakingPaths performs the intra-procedural leak detection technique of Section 3.2.2 and returns any leaking paths in the procedure.The leaking path, if it exists, is used as a summary of the procedure.
Procedures that are free from leaks have an empty path as summary; therefore, they are neutral for inter-procedural analysis.In contrast, procedures that may leak have some non-empty path as summary, which can be combined with the summary of other procedures they call to find out whether the combination of caller and callee is free from leaks.This is done in lines 9-17 of Algorithm 3: the resource-flow graph of a procedure n that calls another procedure m includes some transfer nodes to m; we replace those nodes with the summary of m (which was computed before thanks to the topological sorting), and perform an analysis of the call-free resource-flow graph with summaries.The output of Algorithm 3 are complete summaries for the whole app starting from the entry points.

Implicit Call Sequences
Callbacks in every component used by an Android app have to follow an execution order given by the component's callback graph: a finite-state diagram with callback functions defined on the edges (see Figure 3 for a simplified example).Apps provide implementations of such callback functions, which PLUMBDROID can analyze for leaks.When an edge's transition is taken, all callback functions defined on the edge are called in the order in which they appear.
The documentation of every resource defines callback functions where the resource ought to be released.PLUMBDROID enumerates all paths that first go from the callback graph's entry to the nodes from where the release callback functions can be called, and then continue looping until states are traversed up to D times-where D is a configurable parameter of PLUMBDROID called "unrolling depth" (see Section 4.2.5 to see its impact in practice).Each unrolled path determines a sequence of procedures P 1 ; P 2 ; . . .used in the callback functions in that order.PLUMBDROID looks for leaks in these call sequences by analyzing them as if they were explicit calls in that sequence-using the approach of Section 3.3.1.
For example, Figure 1's resource MediaPlayer should be released in callback function onPause.For a component with the callback graph of Figure 3, and unrolling depth D = 2, PLUMBDROID enumerates the path Starting → Running → Running → Closed , corresponding to callback sequence onCreate(); onStart(); onResume(); onPause(); onResume(); onPause(); . . . .If the media player is acquired and not later released in these call's implementations, PLUMBDROID will detect a leak.Since callback functions onStart and onResume are not implemented in Figure 1's simple example, Figure 4 displays the initial part of this sequence of callbacks by connecting in a sequence the resource-flow graphs of onCreate and onPause.

Fix Generation
Fix templates.Once PLUMBDROID detects a resource leak, fixing it amounts to injecting missing release operations at suitable locations in the app's implementation.PLUMBDROID builds fixes using the conditional template: if (resource != null && held ) resource.r(),where resource is a reference to the resource object, r is the release operation (defined in the resource's API), and held is a condition that holds if and only if the resource is actually not yet released.Calls to release operations must be conditional because PLUMBDROID's analysis is an overapproximation (see Section 3.6) and, in particular, a may leak analysis [42]: it is possible that a leak occurs only in certain conditions, but the fix must be correct in all conditions.Condition held depends on the resource's API: for example, wake locks have a method isHeld() that perfectly serves this purpose; in other cases, the null check is enough (and hence held is just true).Therefore, PLUMBDROID includes a definition of held for every resource type, which it uses to instantiate the template.
Another complication in building a fix arises when a reference to the resource to be released is not visible in the callback where the fix should be added.In these cases, PLUMBDROID's fix will also introduce a fresh variable in the same component where the leaked resource is acquired, and make it point to the resource object.This ensures that a reference to the resource to be released is visible at the fix location.
Fix injection.A fix's resource release statement may be injected into the application at different locations.A simple, conservative choice would be the component's final callback function (onDestroy for activity components).Such a choice would be simple and functionally correct but very inefficient, since the app would hold the resource for much longer than it actually needs it.
Instead, PLUMBDROID uses the information computed during leak analysis to find a suitable release location.As we discussed in Section 3.3.2, the overall output of PLUMBDROID's leak analysis is an execution path that is leaking a certain resource.The path traverses a sequence C 1 ; C 2 ; . . .; C n of callback functions determined by the component's callback graph, and is constructed by PLUMBDROID in a way that it ends with a call C n to the callback function where the resource may be released (according to the resource's API documentation).Therefore, PLUMBDROID adds the fix statement in callback C n just after the last usage of the resource in the callback (if there is any).
In the running example of Figure 1, PLUMBDROID inserts the call to release in callback onPause, which is as early as possible in the sequence of callbacks-as shown in the rightmost node of Figure 4.

Validation
Since leak analysis is sound (see Section 3.6), PLUMBDROID's fixes are correct by construction in the sense that they will remove the leak that is being repaired.However, since the resource release statement that fixes the leak is inserted in the first suitable callback (as described in Section 3.4), it is possible that it interferes in unintended ways with other usages of the resource.
In order to determine whether its fixes may have introduced inconsistencies of this kind, PLUMBDROID performs a final validation step, which runs a modified analysis that checks absence of new leaks as well as absence of use-after-release errors.This analysis reuses the techniques of Section 3.2 and Section 3.3 with the only twist that the pushdown automaton characterizing the property to be checked is now extended to also capture absence of use-after-release errors.
PLUMBDROID's fixes release resources in the recommended callback function, but the app's developer may have ignored this recommendation and written code that still uses the resource in callbacks that occur later in the component's lifecycle.Such scenarios are the usual origin of failed validation: PLUMBDROID would fix the leak but it would also introduce a use-after-release error by releasing the resource too early.
Continuing Figure 1's example of resource MediaPlayer, suppose that the implementation does call the release operation but only in activity onStop.PLUMBDROID would still report a leak, since it does not find a release in onPause-which is where MediaPlayer should be released according to its API documentation.Accordingly, PLUMBDROID's fix for this leak would add release in onPause as described in Section 2. Validation of the leak would, however, fail because the programmer-written release in onStop introduces a double-release of the same resource, which validation detects.
If validation fails, PLUMBDROID still outputs the invalid fix, which can be useful as a suggestion to the developer-who remains responsible for modifying it in a way that doesn't conflict with the rest of the app's behavior.In particular, the experiments of Section 4.2.1 confirm the intuition that validation fails when PLUMBDROID releases resources in the callback function recommended by the official resource documentation but the rest of the app's behavior conflicts with this recommendation.Therefore, the developer has the options of adjusting the fix or refactoring the app to follow the recommended guidelines.
In the running example of MediaPlayer, the programmer may either ignore PLUMB-DROID's suggestion and keep releasing the resource in onStop (against the resource's recommendations), or accept it and remove the late call of release that becomes no longer necessary.
Validation is an optional step in PLUMBDROID.This is because it is not needed if we can assume that the app under repair follows Android's recommendation for when (in which callbacks) a resource should be used and released.As we will empirically demonstrate in Section 4, validation is indeed usually not needed-but it remains available as an option in all cases where an additional level of assurance is required.

Features and Limitations
Let us summarize PLUMBDROID's design features and the limitations of its current implementation.Section 4 will empirically confirm these features and assess the prac-tical impact of the limitations.

Soundness
A leak detection technique is sound [42] if, whenever it finds no leaks for a certain resource, it really means that no such leaks are possible in the app under analysis.
PLUMBDROID's intra-procedural analysis is sound: it performs an exhaustive search of all possible paths, and thus it will report a leak if there is one.The inter-procedural analysis, however, has two possible sources of unsoundness.(a) Since it performs a fixed-depth unrolling of paths in the callback graph (Section 3.3.2),it may miss leaks that only occur along longer paths.(b) Since it ranks procedures according to their call order (Section 3.3.1),and such an order is not uniquely defined if the call graph has cycles, it may miss leaks that only occur in other procedure execution orders.
Both sources of unsoundness are unlikely to be a significant limitation in practice [32].A leak usually does not depend on the absolute number of times a resource is acquired or released, but only on whether acquires and releases are balanced.As long as we unroll each loop a sufficient number of times, unsoundness source (a) should not affect the analysis in practice.Furthermore, leak detection is monotonic with respect to the unrolling depth D: as D increases, PLUMBDROID may find more leaks by exploring more paths, but a leak detected with some D will also always be detected with a larger D > D.
As for the second source of unsoundness, the Android development model, where the overall control flow is determined by implicit callbacks, makes it unlikely that user-defined procedures have circular dependencies.More precisely, PLUMBDROID's soundness is only affected by cycles in paths with acquire and release-not in plain application logic-and hence unsoundness source (b) is also unlikely to occur.
The experiments of Section 4 will confirm that PLUMBDROID is sound in practice by demonstrating that a wide range of Android applications trigger neither source of unsoundness.

Precision
A leak detection technique is precise [42] if it never reports false alarms (also called false positives): whenever it detects a leak, that leak really occurs in some executions of the app under analysis.In the context of leak repair, many false alarms would generate many spurious fixes, which do not introduce bugs (since the analysis is sound) but are useless and possibly slow down the app.
PLUMBDROID's analysis is, as is common for dataflow analyses, flow-sensitive but path-insensitive.This means that it over-approximates the paths that an app may take without taking into account the feasibility of those paths.As a very simple example, consider a program that only consists of statement if (false) res.a(),where res is a reference to a resource and a is an acquire operation.This program is leak free, since the lone acquire will never execute.However, PLUMBDROID would report a leak because it conservatively assumes that every branch is feasible.
Aliasing occurs when different references to the same resource may be available in the same app.Since PLUMBDROID does not perform alias analysis, this is another source of precision loss: a resource with two aliases x and y that is acquired using x and released using y will be considered leaking by PLUMBDROID, which thinks x and y are different resources.
In practice, these two sources of imprecision are limitations to PLUMBDROID's applicability.When aliasing is not present, the experiments of Section 4 indicate that the path-insensitive over-approximation built by PLUMBDROID is very precise in practice.Whether aliasing is present mostly depends on the kind of resource that is analyzed.As we discuss in Section 4.1.1,it is easy to identify resources whose usage is unlikely to introduce aliasing.PLUMBDROID is currently geared towards detecting and repairing leaks of such resources.
A comprehensive empirical study of performance bugs in mobile apps [38] found that about 36% of the analyzed Android resource leaks were related to non-aliasing resources, such as WiFi and Camera, whose operations are energy intensive.The same study also reported that the leaks that affect these resources tend to have a much longer life than the memory-related leaks, as it takes developers longer, on average, to detect and fix the former over the latter.These data indicate that non-aliasing resource leaks are a significant fraction of the most common resource-related issues in Android apps, can have a negative impact on performance, and can be challenging to detect and fix.These observations motivate PLUMBDROID's focus on non-aliasing resources.
PLUMBDROID uses ANDROGUARD-a framework to analyze Android apps-mainly to build the control-flow graphs of methods (which are the basis of our resource-flow graphs) and to process manifest files (extracting information about the components that make up an app).Using ANDROGUARD ensures that the control-flow graphs capture all behavior allowed by Java/Android (including, for example, exceptional control flow) in a simple form in terms of a few basic operations.
APKTOOL-a tool for reverse engineering of Android apps-supports patch generation: PLUMBDROID uses it to decompile an app, modify it with the missing release operations, and recompile the patched app back to executable format.PLUMBDROID's analysis and patching work on Smali code-a human-readable format for the binary bytecode format DEX, which is obtained by decompiling from and compiling to the APK format.

Experimental Evaluation
The overall goal of our experimental evaluation is to investigate whether PLUMB-DROID is a practically viable approach for detecting and repairing resource leaks in Android applications.We consider the following research questions.RQ4: How does PLUMBDROID compare with other automated repair tools for Android resource leaks?

RQ1:
RQ5: How does PLUMBDROID's behavior depend on the unrolling depth parameter, which controls its analysis's level of detail?

Experimental Setup
This section describes how we selected the apps used in the experimental evaluation of PLUMBDROID, how we ran the experiments, and how we collected and assessed the experiments' results to answer the research questions.

Subjects: RQ1, RQ2, RQ3, RQ5
Our experiments to assess correctness and scalability target apps in DROIDLEAKS [29]a curated collection of resource leak bugs in real-world Android applications.DROI-DLEAKS collects a total of 292 leaks from 32 widely used open-source Android apps.For each leak, DROIDLEAKS includes both the buggy (leaking) version of an app and a leak-free version obtained by manually fixing the leak.
Leaks in DROIDLEAKS affect 22 resources.The majority of them (13)  APIs (such as InputStream or BufferReader).PLUMBDROID's analysis is based on the Android programming model, and every Android-specific resource expresses its usage policy in terms of the callback functions where a resource can be acquired or releasedan information that is not available for standard Java API's resources.Therefore, our evaluation only targets leaks affecting Android-specific resources.As we discussed in Section 3.6, PLUMBDROID is oblivious of possible aliases between references to the same resource object.If such aliasing happens within the same app's implementation, it may significantly decrease PLUMBDROID's precision.We found that each Android resource can naturally be classified into aliasing and non-aliasing according to whether typical usage of that resource in an app may introduce multiple references that alias one another. 5Usually, a non-aliasing resource is one that is accessed in strict mutual exclusion, and hence such that obtaining a handle is a relatively expensive operation; Camera, MediaPlayer, and AudioRecorder are examples of non-aliasing resources.In contrast, aliasing resources tend to support a high degree of concurrent access, and hence it is common to instantiate fresh handles for each usage; a database Cursor is a typical example of such resources, as creating a new cursor is inexpensive, and database systems support fine-grained concurrent access.Out of all 13 Android resources involved in leaks in DROIDLEAKS, 9 are non-aliasing; our experiments ran PLUMBDROID on all apps in DROIDLEAKS that use these resources. 6able 1 summarizes the characteristics of the 9 resources we selected for our experiments according to the above criteria.Then, Table 2 lists all apps in DROIDLEAKS that use some of these resources, their size, and how many leaks of each resource DROIDLEAKS includes with fixes.Thus, the first part of our experiments will target 16 Android apps with a total size of about half a million lines of code; DROIDLEAKS collects 26 leaks in these apps affecting the 9 non-aliasing resources we consider.

Subjects: RQ4, RQ5
At the time of writing, RelFix [28] is the only fully automated tool for the detection and repair of Android resource leaks, which can be quantitatively compared to PLUMBDROID.Since RelFix uses Relda2 [55] to detect leaks, and Relda2's experimental evaluation is broader than RelFix's, we also compare PLUMBDROID's leak detection capabilities to Relda2's.
As we discuss in Section 5.3, other tools exist that detect other kinds of leaks; since they are not directly applicable to the same kinds of resources that PLUMBDROID analyzes, we only compare them to PLUMBDROID in a qualitative way in Section 5.
The experimental evaluations of RelFix and Relda2, as reported in their publications [28,55], targeted 27 Android apps that are not part of DROIDLEAKS.Unfortunately, neither detailed experimental results (such as the app versions that were targeted or the actual produced fixes) nor the RelFix and Relda2 tools are publicly available. 7herefore, a detailed, direct experimental comparison is not possible.However, we could still run PLUMBDROID on the same apps analyzed with RelFix and Relda2, and compare our results to those reported by [28,55] in terms of number of fixes and precision.
Out of the 27 apps used in RelFix and Relda2's experimental evaluations, 22 use some of the 9 non-aliasing resources that PLUMBDROID targets (see Table 1).More precisely, Relda2's evaluation in [55] only targets resources that are non-aliasing, thus we consider all of their experiments in our comparison.RelFix's evaluation in [28] targets 4 non-aliasing and 4 aliasing resources; we only consider the former for our comparison with PLUMBDROID.In order to include apps as close as possible to those actually analyzed by [28,55], we downloaded the apk release of each app that was closest in time to the publication time of [28,55].This excluded 2 apps whose older releases we could not retrieve.In all, this process identified 20 apps: 16 used in the evaluation of Relda2 (listed in Table 4) and 4 used in the evaluation of RelFix (listed in Table 5), for a total of 260 000 lines of code and using 7 of the 9 non-aliasing resources.
Relda2 supports both a flow-insensitive and a flow-sensitive detection algorithm.According to [55], the flow-insensitive approach is faster but much less precise.Since PLUMBDROID's analysis is also flow-sensitive, we only compare it to Relda2's flowsensitive analysis (option op 2 in [55]), which is also the one used by RelFix.

Experimental Protocol
In our experiments, each run of PLUMBDROID targets one app and repairs leaks of a specific resource. 8The run's output is a number of leaks and, for each of them, a fix.
After each run, we manually inspected the fixes produced by PLUMBDROID, confirmed that they are syntactically limited to a small number of release operations, and checked that the app with the fixes still runs normally.Unfortunately, the apps do not include tests that we could have used as additional evidence that the fixes did not introduce any regression.However, PLUMBDROID's soundness guarantees that the fixes are correct by construction; and its validation phase further ascertains that the fixes do not introduce use-after-release errors.
In all experiments with DROIDLEAKS, we also tried to match, as much as possible, the leaks detected and repaired by PLUMBDROID to those reported in DROIDLEAKS.This was not always possible: some apps' are only available in obfuscated form, which limits what one can conclusively determine by inspecting the bytecode.In addition, DROIDLEAKS's collection is not meant to be exhaustive: therefore, it is to be expected that PLUMBDROID finds leaks that are not included in DROIDLEAKS.In the experiments with the apps analyzed by RelFix and Relda2, we did not have any "ground truth" to compare them to, but we still performed manual checks and testing.
More precisely, we followed these steps to manually inspect and validate all leak detected by PLUMBDROID: 1.We consider the leaking path on the resource-flow graph reported by PLUMBDROID and determine whether it is feasible.If this is not the case mental evaluation. 8PLUMBDROID can analyze leaks for multiple resources in the same run, but we do not use this features in the experiments in order to have a fine-grained breakdown of PLUMBDROID's performance.
(for example, two elements of the path condition are contradictory), then we classify the leak as a false positive.2. If the leaking path is feasible, we consider the path's matching sequence of callbacks, and use that as a guide to write a test that tries to cover the path on the real program-and thus confirms that the leak is a true positive.For short paths, the path condition usually contains enough information to come up with a test after some trial-and-error.3.In more complex cases (especially paths involving UI interactions), we use Android Studio's Monkey Testing framework [5] to generate several random input sequences that thoroughly exercise the app; then, we monitor the app running on those inputs, and select any execution paths that matched the leaking path on the resource-flow graph.4. Finally, we re-compile the app after injecting the fix produced by PLUMBDROID, and run the patched app on the tests generated as described above, as well as on a few other random inputs and also trying the app interactively, checking that the leak is no longer triggered and there are no other changes in behavior (in particular, no negative impact on performance).In all cases, we were conservative in assessing which leaks and fixes are correct, marking as "confirmed" only cases where the collected evidence that a leak may occur and its fix safely repairs it is conclusive.
The main parameter regulating PLUMBDROID's behavior is the unrolling depth D. We ran experiments with D ranging from 1 to 6, to demonstrate empirically that the default value D = 3 is necessary and sufficient to achieve soundness (i.e., no leaks are missed).
Hardware/software setup.All the experiments ran on a MacBook Pro equipped with a 6-core Intel Core i9 processor and 16 GB of RAM, running macOS 10.15.3, Android 8.0.2 with API level 26, Python 3.6, ANDROGUARD 3.3.5,APKTOOL 2.4.0.

Experimental Results
This section summarizes the results of our experiments with PLUMBDROID, and discusses how the results answer the research questions.

RQ1: Correctness
Column FIXED in Table 3 reports the number of DROIDLEAKS leaks that PLUMB-DROID detected and fixed with a correct fix (i.e., a fix that prevents leaking); column INVALID reports how many of these fixes failed validation (were "unsafe").PLUMB-DROID was very effective at detecting leaks in non-aliasing resources.In particular, it detected and fixed all 26 leaks reported by DROIDLEAKS and included in our experiments (see Table 2), building a correct fix for each of them.In addition, it detected and fixed another 24 leaks in the same apps.
Precision.Empirically evaluating precision is tricky because we lack a complete baseline.By design, DROIDLEAKS is not an exhaustive collection of leaks.Therefore, when PLUMBDROID reports and fixes a leak it could be: (a) a real leak included in DROIDLEAKS; (b) a real leak not included in DROIDLEAKS; (c) a spurious leak.By inspecting the leak reports and the apps (as discussed in Section 4.1.3)we managed to confirm that 44 leaks (88%) reported by PLUMBDROID are in categories (a) (26 leaks or 52%, matching all leaks included in DROIDLEAKS) or (b) (18 leaks or 36%) above-and thus are real leaks (true positives).Unfortunately, the remaining 6 leaks (12%) reported by PLUMBDROID were found in apps whose bytecode is only available in obfuscated form, which means we cannot be certain they are not spurious; these unconfirmed cases are counted in column "?" in Table 3.Even in the worst case in which all of these are spurious, PLUMBDROID's precision would remain high (88%).The actual precision is likely higher: in all cases where we could analyze the code, we found a real leak; unconfirmed cases probably just require more evidence such as access to unobfuscated bytecode.Anyway, note that any spurious fixes would still be safe to apply-albeit unnecessary-because they do not introduce bugs: since all release operations added by PlumbDroid are conditional (Section 3.4), a fix "repairing" a spuriously detected leak simply introduces release operations that is neve executed in actual program executions.
Correctness and safety.All fixes built by PLUMBDROID are correct in the sense that they release resources so as to avoid a leak; manual inspection, carried out as described in Section 4. 1.3, confirmed this in all cases-with some remaining uncertainty only for obfuscated apps.
PLUMBDROID's validation step assesses "safety": whether a fix does not introduce a use-after-release error.All but 5 fixes built by PLUMBDROID for non-aliasing resources are safe.The 5 unsafe fixes are: (i) Three identical fixes (releasing the same resource in the same location) repairing three distinct leaks of resource MediaPlayer in app SureSpot.
According to the Android reference manual [6], this resource can be released either in the onPause or in the onStop callback.PLUMBDROID releases resources as early as possible by default, and hence it built a fix releasing the MediaPlayer in onPause.The developers of SureSpot, however, assumed that the resource is only released later (in onStop), and hence PLUMBDROID's fix introduced a useafter-release error that failed validation.
To deal with such situations-resources that may be released in different callbacks-we then could introduce a configuration option to decide whether to release resources early or late.An app developer could therefore configure our analyzer in a way that suits their design decisions.In particular, configuring PLUMBDROID with option late in these cases would generate fixes that pass validation.
(ii) Two identical fixes (releasing the same resource in the same location) repairing two distinct leaks of resource LocationListener in app Ushahidi.
The fix generated by PLUMBDROID failed validation because the app's developers assumed that the resource is only released in callback onDestroy.This assumption conflicts with Android's recommendations to release the resources in earlier callbacks.
In this case, the best course of action would be amending the app's usage policy of the resource so as to comply with Android's guidelines.PLUMBDROID's fix would pass validation after this modification.
Note that PLUMBDROID does not output fixes that do not pass the validation step; therefore, there is no risk that such unsafe fixes are accidentally deployed.) method with a resource leak (code in black, executed in callback onPause()), and how the leak was patched by the app developers in commit 113555e9ae (code in orange).PLUMBDROID generates a patch for this leak that exactly matches the developer-written one shown here.

RQ2: Comparison with Developer Fixes
The manual inspection and validation protocol (Section 4.1.3)that we followed to confirm the correctness of all leaks and fixes reported by PLUMBDROID already strongly suggests that the results of PLUMBDROID's analysis are usually of high quality.To better understand whether PLUMBDROID's fixes are comparable to those written by developers, we further scrutinized the fixes produced by PLUMBDROID for leaks in apps IRCCloud and Ushahidi.We selected these two apps as they are among the largest in the DROIDLEAKS collection, they are open source, and their public code repositories are well organized and feature a long-running development history.Furthermore, as shown in Table 3, PLUMBDROID detected and fixed 5 leaks in IRCCloud; and detected 2 leaks in Ushahidi, for which it could only produce fixes that fail the validation step.Thus, there is a mix of cases where PLUMBDROID is completely successful and cases where PLUMBDROID's validation fail-which mitigates the risk of biasing the analysis in PLUMBDROID's favor.
Based on these results, we went through the bug reports and commit history of the two apps, looking for developer-written fixes of the 7 leaks that PLUMBDROID detected and fixed.Indeed, we found that developers eventually found and fixed all these leaks, 9Figure 9: An excerpt of class NetworkConnection in Android app IRCCloud, showing the removeHandler() method with a resource leak (code in black, executed in callback onPause()), and how it was fixed by the app developers (Figure 9a) and by PLUMBDROID (Figure 9b).which confirms that they are considered serious enough faults.
In 2 out of the 5 leaks in IRCCloud, the fix produced by PLUMBDROID is identical to the developer-written one, as they both release the same resource in the same location.Figure 8 shows one of these leaks and its fix. 10 In the other 3 leaks in IRCCloud, the fix produced by PLUMBDROID released the same resource as the developer-written one but in a different location of the same basic block.Figure 9 shows one of these leaks and its fix by developer (Figure 9a) and by PLUMBDROID (Figure 9b).In all these cases, the difference of release location is immaterial, as the statements that are between the release point in the developer-written fix and the release point in PLUMBDROID's fix are simple assignments do not affect any shared resources and execute quickly.
In both leaks in Ushahidi, the difference between the (invalid) fixes produced by PLUMBDROID and the developer-written ones is also the location of the release.Sticking to the Android developer guidelines [4], PLUMBDROID only releases the resource LocationListener in the callback onPause() for one of these leaks; doing so fails the validation phase, since the Ushaidi app still uses location resources when it is running in the background.Therefore, the developers fixed the leak by releasing the resource in the callback onDestroy(), that is only when the app is shut down.The other leak has a similar discrepancy between the Android guidelines followed by PLUMBDROID and how the Ushahidi app is written.
In all, PLUMBDROID's fixes are often very similar and functionally equivalent to those written by programmers for the same leaks.PLUMBDROID's validation phase is useful to detect when an app deviates from Android's guidelines on resource management; in these cases, the user of PLUMBDROID can decide whether to refactor the app to follow the guidelines, or modify PLUMBDROID so that it generates a fix at a different location.
The similarity between PLUMBDROID and developer-written fixes, as well their usual syntactic simplicity, is also evidence that these fixes are unlikely to negatively alter the running-time performance of an app (and hence the user experience).This is also consistent with our manual analysis (Section 4.1.3),which never found an app's responsiveness to worsen after applying a resource-leak fix.
According to the analysis of a sample, we found that the fixes produced by PLUMBDROID often are functionally equivalent to those written by the app developers.

RQ3: Performance
Columns TIME in Table 3 report the running time of PLUMBDROID in each step.As we can expect from a tool based on static analysis, PLUMBDROID is generally fast and scalable on apps of significant size.Its average running time is around 5 minutes per app-resource and around 2 minutes per repaired leak (121 s 6084.8/50).
The ANALYSIS step dominates the running time, since it performs an exhaustive search.In contrast, the ABSTRACTION step is fairly fast (as it amounts to simplifying control-flow graphs); and the FIXING step takes negligible time (as it directly builds on the results of the analysis step).
PLUMBDROID's abstractions are key to its performance, as we can see from Table 3's data about the size of the resource-flow graphs.Even for apps of significant size, the resource-flow graph remains manageable; more important, its cyclomatic complexity M -a measure of the number of paths in a graph [39]-is usually much lower than the cyclomatic complexity M of the full control-flow graph, which makes the exhaustive analysis of a resource-flow graph scalable.
PLUMBDROID is scalable: it takes about 2 minutes on average to detect and fix a resource leak.

RQ4: Comparison with Other Tools
Comparison with Relda2.running TIME in seconds, the number of leaks DETECTED and FIXED by PLUMBDROID, how many of these leaks we could conclusively classify as real leaks ( , true positives), and the number of fixes that PLUMBDROID classified as INVALID (that is, they failed validation).These results are compared to the number of leaks DETECTED and FIXED by Relfix, and how many of these are considered real leaks ( ) according to the experiments reported in [28].The two bottom rows report the AVERAGE (mean) and TOTAL for all apps/resources.and hence PLUMBDROID reports several more true leaks (70 vs. 46).The difference between the two tools varies considerably with the app.On 4 apps (Andless, PicsArt, Vplayer, and Yelp) both tools detect the same number of leaks with the same (high) precision; even though we cannot verify this conjecture, it is quite possible that exactly the same leaks are detected by both tools in these cases.On 2 apps (Impeller and CheckCheck), neither tool is strictly better: when PLUMBDROID outperforms Relda2 in number of confirmed detected leaks (app Impeller) it also achieves a lower precision; when PLUMBDROID outperforms Relda2 in precision (app CheckCheck) it also finds one less correct leak.On the remaining 11 apps (Apollo, Jane, MiguMusic, QRScab, Runnerup, Shopsavvy, SimSimi, SuperTorch, TigerMap, Utorch, and Weath-erPro) PLUMBDROID is at least as good as Relda2 in both number of confirmed detected leaks and precision, and strictly better in detected leaks, precision, or both.We cannot directly compare PLUMBDROID's and Relda2's running times, since we could not run them on the same hardware, but we notice that the running times reported in [55] are in the ballpark of PLUMBDROID's.In all, PLUMBDROID's leak detection capabilities often outperforms Relda2's on the non-aliasing resources that we currently focus on.
Comparison with RelFix.Table 5 compares the fixing capabilities of PLUMB-DROID and RelFix (which uses Relda2 for leak detection) on the 4 non-aliasing resources used in the latter's experiments [28].Here too PLUMBDROID generally appears more effective than RelFix: conservatively assuming that all fixes reported by [28]  genuine and "safe", 11 PLUMBDROID has higher precision (82%= 9/11 vs. 64%= 7/11) and fixes at least as many confirmed leaks (even after discarding those that fail validation).PLUMBDROID generates small patches, each consisting of just 11 bytecode instructions on average, which corresponds to an average 0.017% increase in size of a patched app.This approach leads to much smaller patches than RelFix's, whose patches also include instrumentation to detect the leaks on which the fixes depend to function correctly.As a result, the average increase in size introduced by a RelFix patch is 0.3% in terms of bytecode instructions [28], which is one order of magnitude larger than PLUMBDROID's.
As explained in Section 4.1.2,all results in this section are subject to the limitation that a direct comparison with Relda2 and RelFix was not possible.Despite this limitation, the comparison collected enough evidence to indicate that PLUMBDROID's analysis is often more thorough and more precise than the other tools'.
On non-aliasing resources, PLUMBDROID is usually more effective and precise than other techniques for the automated detection and repair of Android resource leaks.

RQ5: Unrolling
In the experiments reported so far, PLUMBDROID ran with the unrolling depth parameter D = 3, which is the default.Table 6 summarizes the key data about experiments on the same apps but using different values of D. These results indicate that a value of D ≥ 3 is required for soundness: PLUMBDROID running with D = 1 missed 24 leaks (10 in DROIDLEAKS, and 14 in the apps used by Relda2/RelFix); with D = 2 it missed 5 leaks (all in the apps used by Relda2/RelFix).All missed leaks only occur with resources that are acquired multiple times-that is they affect reentrant resources: WakeLock and WifiLock in apps CallMeter, CSipSimple, IRCCloud (from DROIDLEAKS), CheckCheck, Impeller, PicsArt, SimSimi (from the comparison with Relda2), and BlueChat (from the comparison with RelFix).
Is D = 3 also sufficient for soundness?While we cannot formally prove it, the experiments suggest this is the case: increasing D to larger values does not find new leaks but only increases the running time.Unsurprisingly, the running time grows conspicuously with the value of D, since a larger unrolling depth determines a combinatorial increase in the number of possible paths.Thus, for the analyzed apps, the default D = 3 is the empirically optimal value: it achieves soundness without unnecessarily increasing the running time.It is possible this result does not generalize to apps with more complex reentrant resource management; however, PLUMBDROID always offers the possibility of increasing D until its analysis is sufficiently exhaustive.
PLUMBDROID's analysis is sound provided it unrolls callback loops a sufficient number of times (thrice in the experiments).

Aliasing Resources
We repeatedly remarked that PLUMBDROID's current implementation is effective only on non-aliasing resources; it remains applicable to aliasing resources, but it is bound to generate a large number of false positives.In order to get a clearer picture of PLUMBDROID's limitations in the presence of aliasing, this section reports some additional experiments on aliasing resources.It remains that our contributions focus on non-aliasing resources; an adequate support of aliasing belongs to future work.[28]) and PLUMBDROID (on the programs in DROIDLEAKS).The table reports the number of aliasing RESOURCES involved in leaks, the reported LEAKS, how many of them are confirmed true leaks , and the corresponding precision /LEAKS.
Table 7 shows the behavior of PLUMBDROID on leaks of the 6 aliasing resources in DROIDLEAKS apps.PLUMBDROID reported a total of 273 leaks, but we could only confirm about one third of them as real leaks (true positives).This is a lower bound on PLUMBDROID's precision on aliasing resources, as it's possible that more reported leaks are real but we could not conclusively confirm them as such because they affect obfuscated apps.Nevertheless, it's clear the precision is much lower than on nonaliasing resources-as we expected.
For comparison, Table 7 also reports the performance of Relda2 according to the experiments reported in [28] on 4 aliasing resources (Section 4.2.4 discusses the data from the same source but involving non-aliasing resources).Relda2 reported a total of 108 leaks, but only 22% of them are real leaks according to [28].Even though the experiments with PLUMBDROID and with Relda2 are not directly comparable, it's clear both tools achieve a low precision on aliasing resources-arguably low to the point that practical usefulness is severely reduced.

Threats to Validity
The main threats to the validity of our empirical evaluation come from the fact that we analyzed Android apps in bytecode format; furthermore, some of these apps' bytecode was only available in obfuscated form.In these cases, we were not able to inspect in detail how the fixes modified the original programs; we could not always match with absolute certainty the leaks and fixes listed in DROIDLEAKS with the fixes produced by PLUMBDROID; and we could not run systematic testing of the automatically fixed apps.This threat was significantly mitigated by other sources of evidence that PLUMBDROID indeed produces fixes that are correct and do not alter program behavior except for removing the source of leaks: first, the manual inspections we could carry out on the apps that are not obfuscated confirmed in all cases our expectations; second, PLUMBDROID's analysis is generally sound, and hence it should detect all leaks (modulo bugs in our implementation of PLUMBDROID); third, running the fixed apps for significant periods of time did not show any apparent change in their behavior.
As remarked in Section 4.1.2,we could only perform an indirect comparison with Relda2/RelFix (the only other fully automated approach for the repair of Android resource leaks that is currently available) since neither the tools nor details of their experiments other than those summarized in their publications [55,28] are available.To mitigate the ensuing threats, we analyzed app versions that were available around the time when the Relda2/RelFix experiments were conducted, and we excluded from the comparison with PLUMBDROID measures that require experimental repetition (such as running time).While it is still possible that measures such as precision were assessed differently than how we did, these should be minor differences that do not invalidate the high-level results of the comparison.
Our evaluation did not assess the acceptability of fixes from a programmer's perspective.Since PLUMBDROID works on bytecode, its fixes may not be easily accessible by developers familiar only with the source code.Nonetheless, fixes produced by PLUMBDROID are succinct and correct by construction, which is usually conducive to readability and acceptability.As future work, one could implement PLUMBDROID's approach at the level of source code, so as to provide immediate feedback to programmers as they develop an Android app.PLUMBDROID in its current form could instead be easily integrated in an automated checking system for Android apps-for example, within app stores.
We didn't formally prove the soundness or precision of PLUMBDROID's analysis, nor that our implementation is free from bugs.Since PLUMBDROID is implemented on top of ANDROGUARD [8] and APKTOOL [10] (Section 3.7), any bugs or limitations of these tools may affect PLUMBDROID's analysis.In particular, ANDROGUARD cannot currently analyze native code 12 -a common limitation of static analysis.By and large, however, these tools' support of Android is quite extensive, and hence any current limitations are unlikely to significantly impact the soundness of the results obtained in PLUMBDROID's experimental evaluation.
Nonetheless, we analyzed in detail the features of PLUMBDROID's analysis both theoretically (Section 3.6) and empirically (Section 4).The empirical evaluation corroborates the evidence that PLUMBDROID is indeed sound (for sufficiently large unrolling depth D), and that aliasing is the primary source of imprecision.In future work, we plan to equip PLUMBDROID with alias analysis [23], in order to boost its precision on the aliasing resources that currently lead to many false positives.
DROIDLEAKS offers a diverse collection of widely-used apps and leaked resources, which we further extended with apps used in Relda2/RelFix's evaluations.In our experiments, we used all apps and resources in DROIDLEAKS and in Relda2/RelFix's evaluations that PLUMBDROID can analyze with precision.This helps to generalize the results of our evaluation, and led to finding numerous leaks not included in DROIDLEAKS nor found by Relda2/RelFix.Further experiments in this area would greatly benefit from extending curated collections of leaks and repairs like DROIDLEAKS.Our replication package is a contribution in this direction.

Automated Program Repair
PLUMBDROID is a form of automated program repair (APR) targeting a specific kind of bugs (resource leaks) and programs (Android apps).The bulk of "classic" APR research [19,41,51,37] usually targets general-purpose techniques, which are applicable in principle to any kinds of program and behavioral bugs.The majority of these techniques are based on dynamic analysis-that is, they rely on tests to define expected behavior, to detect and localize errors [21,15], and to validate the generated fixes [35,22,45].General-purpose APR completely based on static analysis is less common [33,34,18], primarily because tests are more widely available in generalpurpose applications, whereas achieving a high precision with static analysis is challenging for the same kind of applications and properties.

Leak Analysis
Whereas PLUMBDROID is one of only two fully automated approaches for fixing Android resource leaks (the other is RelFix, discussed below and in Section 4.2.4), detection of leaks and other defects is more widely studied and has used a broad range of techniques-from static analysis to testing.Table 8 outlines the features of the main related approaches, which we discuss in the rest of this section.

Static Analysis
Approaches based on static analysis build an abstraction of a program's behavior, which can be searched exhaustively for leaks.Since Android apps run on mobile devices, they are prone to defects such as privacy leaks [20], permission misuses [27], and other security vulnerabilities [57,43] that are less prominent (or have less impact) in traditional "desktop" applications.In such specialized domains, where soundness of analysis is paramount, static analysis is widely applied-for example to perform taint analysis [36] and other kinds of control-flow based analyses [26,11].Indeed, there has been plenty of work that applied static analysis to analyze resource management in Java [50,16], including detecting resource leaks [47,23].
Whereas some of these contributions could be useful also to analyze mobile apps written in Java, in order to do so the techniques should first be extended to support the peculiarities of the Android programming model-in particular, its event-driven control flow.
General-purposes static analyzers for Java like FindBugs [17], are also capable of detecting a variety of issues in common Java resources (e.g., files); however, FindBugs is neither sound nor very precise [49], as it is based on heuristics and pattern-matching that are primarily geared towards detecting stylistic issues and code smells.

Dynamic Analysis
Many approaches use dynamic analysis (testing), and hence are not sound (they may miss leaks).
One example is a test-generation framework capable of building inputs exposing resource leaks that lead to energy inefficiencies [13].Since it targets energy efficiency, the framework consists of a hybrid setup that includes hardware to physically measure energy consumption, which makes it less practical to deploy (hence, Table 8 classifies it as "partial" automation).Its measurements are then combined with more traditional software metrics to generate testing oracles for energy leak detection.The framework's generated tests are sequences of UI events that trigger energy leaks or other inefficiencies exposed by the oracles.As it is usual for test-case generation, [13]'s framework is based on heuristics and statistical assumptions about energy consumption patterns, and hence its detection capabilities are not exhaustive (i.e., not sound).
LeakCanary [24] and the Android Studio Monitor [7] are two of the most popular tools used by developer to detect memory leaks as they have high precision and are fully automated.Like all approaches based on testing, they are unsound in general, and their capabilities strongly depend on the quality of the tests that are provided.
FunesDroid [2] generates inputs that correspond to pre-defined user interactionslike rotating the screen-which can trigger memory leaks when executed in certain activities.Besides being unsound like all testing techniques, FunesDroid's testing capabilities are also limited by the kinds of interactions that it supports.Furthermore, FunesDroid's test generation capabilities are not fully automated for leak detection: while the tool provides user interactions as inputs, one still needs to provide tests that run the app where leaks are being detected.
Sentinel [54,52], an approach based on generating GUI events for testing, models resource usage as context-free languages, and hence it is one of the few leak analysis techniques that is capable of fully modeling reentrant resources.The tool first performs a static analysis of app code to build a model that maps GUI events to callback methods that affect sensor behavior.Then, it traverses the model to enumerate paths, which in turn are used to generate test cases.The last step (from paths to actual test inputs) requires users to manually come up with suitable inputs that match the abstract paths; therefore, the Sentinel approach is not fully automated.

Leak Repair
The amount of work on detecting various kinds of leaks [12,13,55,31,44] and the recent publication of the DROIDLEAKS curated collection of leaks [29] indicate that leak detection is considered a practically important problem in Android programming.In this section, we discuss in greater detail two approaches that are also capable, like PLUMBDROID, of fixing the Android leaks they detect.

Relda2 and RelFix
Relda2 [55] combines flow-insensitive and flow-sensitive static analyses to compute resource summaries: abstract representations of each method's resource usage, which can be combined to perform leak detection across different procedures and callbacks.Since Relda2 approximates loops in an activity's lifecycle by abstracting away some of the flow information (even in its "flow-sensitive" analysis), and does not accurately track nested resource acquisitions, its analysis is generally unsound (leaks may go undetected) and imprecise (spurious errors may be reported).In contrast, PLUMB-DROID performs a more thorough and precise inter-procedural analysis by considering all possible callback sequences.PLUMBDROID even allows users to set the unrolling depth D (affecting the maximum length of analyzed callback sequences), which is a means of trading off soundness (i.e., how thorough the analysis is) with running time (i.e., how long/how many computational resources the analysis takes).PLUMB-DROID's modeling of resources is more detailed than Relda2's also because it supports a validation step (Section 3.5), which can detect inconsistencies between a resource's recommended usage guidelines and how it is actually used by an app.After building a control-flow model of resource usages, Relda2 uses an off-the-shelf model checker to analyze it.In contrast, PLUMBDROID uses a custom automata-theoretic analysis algorithm to search for leaks on resource-flow graphs, which may contribute to more precise and scalable results.
RelFix [28] can patch resource leaks in Android apps that have been detected by Relda2.It applies patches at the level of Dalvik bytecode, whereas PLUMBDROID does so at the level Smali (a human-readable format of Dalvik), which makes PLUMBDROID's output more accessible to human programmers.Section 4.2.4 discussed a detailed comparison between PLUMBDROID and Relda2/RelFix in terms of precision and patch sizes.Another significant difference is how they build fixes: RelFix follows the simple approach of releasing resources in the very last callback of an activity's lifecycle, whereas PLUMBDROID builds fixes that adhere to Android's recommended guidelines.

EnergyPatch
EnergyPatch [12,14] is another approach for leak detection based on static techniques where resource usage are modeled as regular expressions.EnergyPatch uses abstract interpretation to compute an over-approximation of an app's energy-relevant behavior; then, it performs symbolic execution to detect which abstract leaking behaviors are false positives and which are executable (i.e., correspond to a real resource leak); therefore, its analysis is hybrid as it combines static and dynamic techniques.For each executable leaking behavior, symbolic execution can also generate a concrete program input that triggers the energy-leak bug.EnergyPatch targets a different kind of resource leaks (energy-consumption related, which lead to a wasteful usage of a mobile device's energy resources) than PLUMBDROID.Since EnergyPatch only analyzes simple paths (i.e., without loops) in the callback graph, its analysis may be unsound (especially for reentrant resources).
While EnergyPatch focuses on leak detection, it also offers a simple technique for generating fixes, which simply releases all resources in the very last callback of an activity's lifecycle.As we discussed in Section 3.4, this approach is sometimes impractical because it may conflict with some of Android programming's best practices.In contrast, PLUMBDROID releases the resource aggressively, in the earliest callback, since our validation step later can filter out patches that result in use-after-release issues.

Conclusions and Future Work
This paper presented PLUMBDROID: a technique and tool to detect and automatically fix resource leaks in Android apps.PLUMBDROID is based on succinct static abstractions of an app's control-flow; therefore, its analysis is sound and its fixes are correct by construction.Its main limitation is that its analysis tends to generate false positives on resources that are frequently aliased within the same app.In practice, this means that PLUMBDROID's is currently primarily designed for the numerous Android resources that are not subject to aliasing.On these resources, we demonstrated PLUMBDROID's effectiveness and scalability.Extending PLUMBDROID's approach with aliasing information is an interesting and natural direction for future work.

public class ImageViewerActivity extends Activity {privateFigure 1 :
Figure 1: An excerpt of class ImageViewerActivity in Android app IRCCloud, showing a resource leak that PLUMBDROID can fix automatically.

Figure 2 :
Figure2: How PLUMBDROID works: First, PLUMBDROID builds a finite-state ABSTRACTION of the Android app under analysis, which captures acquire and release operations of an API's resources.The abstraction models each function of the application with a resource-flow graph (RFG)-a special kind of control-flow graph-and combines resource-flow graphs to model inter-procedural behavior.In the ANALYSIS step, PLUMBDROID searches the graph abstraction for resource leaks: paths where a resource k is acquired (a k ) but not eventually released.In the FIXING step, PLUMBDROID injects the missing release operations r k where needed along the leaking path.In the final VALIDATION step, PLUMBDROID abstracts and analyzes the code after fixing, so as to ensure that the fix does not introduce unintended interactions that cause new resource-usage related problems.

Figure 3 :
Figure 3: Simplified callback graph of an Android component.

Algorithm 2 :
3); in other words, intra-procedural Input: control-flow basic block b, resource list L Output: resource path graph p p ← ∅ // initialize p to empty graph foreach statement s in block b do if s invokes a resource acquire operation a in L n ← new AcquireNode(a) elseif s invokes a resource release operation r in L n ← new ReleaseNode(r) elseif s invokes any other operation o n ← new TransferNode(o) elseif s is a return statement n ← new ExitNode else n ← NULL if n = NULL append node n to path graph p's tail // if b contains no resource-relevant statements if p = ∅ p ← new TrivialNode // return a trivial node Algorithm 1: Algorithm Path that builds the resource path graph p modeling control-flow basic block b.Input: control-flow graph C, resource list L Output: resource-flow graph R foreach block b in control-flow graph C do // p(b) is the path graph corresponding to b ∈ C p(b) ← Path(b, L) // call to Algorithm 1 R ← { entry node s } c 0 ← the entry block of C add an edge from s to p(c 0 )'s entry foreach block b 1 in control-flow graph C do foreach block b 2 in b 1 's successors in C do add an edge from p(b 1 )'s exit to p(b 2 )'s entry foreach ExitNode e in p(b 1 ) do add an edge from e's predecessors to f (the exit node of R) Algorithm RFG that builds a resource-flow graph R modeling control-flow graph C.

Figure 4 :
Figure4: Some abstractions built by PLUMBDROID to analyze the example of Figure1.The intra-procedural analysis described in Section 3.2 builds a resource-flow graph (RFG) for each procedure onCreate and onPause independently.As described in Section 3.3, the inter-procedural analysis considers, among others, the sequence of callback functions onCreate(); onStart(); onResume(); onPause(); since onStart() and onResume() do nothing in this example, this corresponds to connecting onCreate's exit to onPause's entry.The inter-procedural analysis thus finds a leaking path (in orange), where acquire operation new is not matched by any release operation.Fixing (Section 3.4) modifies the app by adding a suitable release operation player.release()(in green), which completely removes the leak.

Figure 7 :
Figure 7: The intersection automaton A X (right) combines the complement automaton AL M (left) of the MediaPlayer's resource automaton AL M from Figure 6b and the flow automaton AR (middle) of method onCreate() from Figure 1.

Figure 8 :
Figure8: An excerpt of class NetworkConnection in Android app IRCCloud, showing the disconnect() method with a resource leak (code in black, executed in callback onPause()), and how the leak was patched by the app developers in commit 113555e9ae (code in orange).PLUMBDROID generates a patch for this leak that exactly matches the developer-written one shown here.

Table 1 :
Does PLUMBDROID generate fixes that are correct and "safe"?RQ2: How do PLUMBDROID's fixes compare to those written by developers?RQ3: Is PLUMBDROID scalable to real-world Android apps?Android resources analyzed with PLUMBDROID.For each RESOURCE, the table reports the acquire a k and release r [3]PERATIONS it supports (according to the resource's API documentation[3]), the CALLBACK function on... where the resource should be RELEASED (according to the Android developer guides [4]), and whether the resource is REENTRANT (Yes implies that absence of leaks is a context-free property and No implies that it is a regular property).

Table 2 :
are Androidspecific resources (such as Camera or WifiLock), while the others are standard Java DROIDLEAKS apps analyzed with PLUMBDROID.For each APP, the table reports its size KLOC in thousands of lines of code.For each RESOURCE used by the app, the table then reports the number of LEAKS of that resource and app included in DROIDLEAKS.The two bottom rows report the AVERAGE (mean) and TOTAL for all apps.

Table 3 :
Results of running PLUMBDROID on apps in DROIDLEAKS.For every APP, the table reports the number of nodes |V | and edges |E| of its resource-flow graph RFG, and the ratio M/M between the RFG's cyclomatic complexity M and the cyclomatic complexity M of the whole app's control-flow graph.For every RESOURCE used by the app, the table then reports PLUMBDROID's running time to perform each of the steps of Figure2(ABSTRACTION, ANALY-SIS, FIXING, and VALIDATION); as well as the TOTAL running time; since the abstraction is built once per app, time ABSTRACTION is the same for all resources used by an app.Finally, the table reports the number of leaks of each resource detected and FIXED by PLUMBDROID; how many of these fixed leaks we could not conclusively classify as real leaks (?); and the number of the fixes that PLUMBDROID classified as INVALID (that is, they failed validation).The two bottom rows report the AVERAGE (mean, per app or per app-resource) and TOTAL in all experiments.

Table 4 :
[55]arison of PLUMBDROID's and Relda2's leak detection capabilities.For every APP used in the comparison, the table reports its size KLOC in thousands of lines of code, and the resource analyzed for leaks.Then, it reports PLUMBDROID's running TIME in seconds, the number of LEAKS PLUMBDROID detected, and how many of these we definitely confirmed as true positives by manual analysis ( ).These results are compared to the number of LEAKS detected by Relda2, and how many of these were true positives ( ) according to the experiments reported in[55].The two bottom rows report the AVERAGE (mean) and TOTAL for all apps/resources.

Table 5 :
Comparison of PLUMBDROID's and RelFix's leak repair capabilities (on non-aliasing resources).For every APP used in the comparison, the table reports its size KLOC in thousands of lines of code, and the resources whose leaks are repaired.Then, it reports PLUMBDROID's

Table 6 :
Results of running PLUMBDROID with different unrolling depths on the DROIDLEAKS benchmark and on the apps used in the comparison with Relda2 and RelFix.For each unrolling depth D, the table reports the AVERAGE (mean, per app-resource) running TIME of PLUMBDROID on all leaks of non-aliasing resources; and the total number of FIXED LEAKS and MISSED LEAKS (not detected, and hence not fixed).The row with D = 3 corresponds to the DROIDLEAKS data in Table3, and the Relda2/RelFix data in Tables 4-5.

Table 7 :
Detection of leaks of aliasing resources by Relda2 (according to the experiments reported in

Table 8 :
Comparison of tools that detect and repair leaks in Android apps.For each tool, the table report the kinds of code ANALYSIS it performs (static or dynamic), the kinds of LEAKS it primarily targets, whether it is fully or partially AUTOMATED, whether it models REENTRANT behavior, whether its detection is SOUND, and whether it can also generate REPAIRs of the detected leaks.Entries (Yes) in column REPAIR denote fixes that release any leaking resource at the very end of an app's lifecycle, without following the resource-specific Android guidelines.