Study and Refactoring of Android Asynchronous Programming Yu Lin, Semih Okur Danny Dig Computer Science Department University of Illinois at Urbana-Champaign, USA {yulin2, okur2}@illinois.edu School of Electrical Engineering and Computer Science Oregon State University digd@eecs.oregonstate.edu “Home” button and navigates back, etc. If the AsyncTask is still running and it holds GUI reference, the destroyed GUI cannot be garbage collected, which leads to memory leaks. Abstract—To avoid unresponsiveness, a core part of mobile development is asynchronous programming. Android provides several async constructs that developers can use. However, developers can still use the inappropriate async constructs, which result in memory leaks, lost results, and wasted energy. Fortunately, refactoring tools can eliminate these problems by transforming async code to use the appropriate constructs. On the other hand, if an AsyncTask that finished its job updates a GUI component that has already been destroyed and recreated, the update is sent to the destroyed GUI rather than the recreated new one, and cannot be seen by the user. Thus, the task result is lost, frustrating the user. Moreover, the device wasted its energy to execute a task whose result is never used. As pointed out by many forums [1], [4], [6], this problem is widespread and is critical for long-running tasks. IntentService and AsyncTaskLoader do not have the above limitations because they do not hold a reference to GUI and instead use a radically different mechanism to communicate with the GUI. To avoid the above problems of AsyncTask, developers must refactor AsyncTask code into enhanced async constructs such as IntentService. In this paper we conducted a formative study on a corpus of 611 widely-used Android apps to map the asynchronous landscape of Android apps, understand how developers retrofit asynchrony, and learn about barriers encountered by developers. Based on this study, we designed, implemented, and evaluated A SYNC D ROID, a refactoring tool which enables Android developers to transform existing improperly-used async constructs into correct constructs. Our empirical evaluation shows that A SYNC D ROID is applicable, accurate, and saves developers effort. We submitted 30 refactoring patches, and developers consider that the refactorings are useful. I. I NTRODUCTION However, manually applying this refactoring is non-trivial due to drastic changes in communication with GUI. This is a challenging problem because a developer needs to transform a shared-memory based communication (through access to the same variables) into a distributed-style (through marshaling objects on special channels). First, the developer needs to determine which objects should flow into or escape from IntentService. Unlike AsyncTask, the objects that flow into or escape from IntentService should be serializable. Determining this requires tracing the call graph and type hierarchy. Second, the developer needs to rewire the channels of communication. Whereas AsyncTask provides handy event handlers for callback communication, IntentService does not. IntentService and GUI can only communicate through sending and receiving broadcast messages. This requires developer to replace event handlers with semanticequivalent broadcast receivers, which is tedious. Third, the developer needs to infer where to register the broadcast receivers. Registering at inappropriate places can still lead to losing task results. According to a Gartner report [9], by 2016 more than 300 billion apps for smartphones and tablets will be downloaded annually. Android is the dominant platform, by 4x over the next largest platform and 1.7x over all the others combined [16]. Previous studies [37], [49] have shown that unresponsiveness is the number one bug that plagues Android apps. To avoid unresponsiveness, app developers use asynchronous programming to execute CPU-bound or blocking I/O operations (e.g., accessing the cloud, database, filesystem) in background and inform the app when the result becomes available. In order to make asynchronous programming easier, Android provides three major async constructs: AsyncTask, IntentService and AsyncTaskLoader. AsyncTask is designed for encapsulating short-running tasks while the other two are good choices for long-running tasks. However, as our formative study on a corpus of 611 shows, AsyncTask is the most widely used construct, dominating by a factor of 3x over the other two choices combined. However, if improperly used, AsyncTask can lead to memory leaks, lost results, and wasted energy. Our previous study [36] found that developers usually hold a reference to a GUI component in an AsyncTask, so that they can easily update GUI based on task results. However, there are several instances in which the Android system can destroy and recreate a GUI component while an AsyncTask is running: when a user changes the screen orientation, or navigates to another screen on the same app, switches to another app, clicks the In this paper we first present a formative study to understand how developers use different Android async constructs. We analyzed a corpus of 611 most popular open-source Android apps, comprising 6.47M SLOC. To further put the study results in a broader context, we then surveyed 10 expert Android developers. The formative study answers the following questions: RQ1: How do Android developers use asynchronous pro1 gramming? Mapping the landscape of usage of async constructs in Android is useful for researchers, library designers, and is educational for developers. We found that 161 (32%) of the studied apps use at least one asynchronous programming, resulting in 1893 instances. Out of these, AsyncTask is the most widely used. IntentService). The algorithm determines the incoming and outgoing objects in/from IntentService, replaces event handlers with broadcast messages and receivers, and infers where to register broadcast receivers. Tool: We implemented the algorithms in A SYNC D ROID, a refactoring tool built on top of Eclipse refactoring engine. RQ2: How do Android developers retrofit asynchrony into existing apps? Must asynchrony be designed into a program, or can it be retrofitted later? What are the most common transformations to retrofit asynchrony? Answering this question is important for software evolution researchers, as well as tool builders. We found widespread use of refactorings, both from sequential code to async, and from basic async to enhanced async. We found the following code evolution scenario: developers first convert sequential code to AsyncTask, and those that continue to evolve the code for better use of asynchrony refactor it further into enhanced constructs. Evaluation: We evaluated A SYNC D ROID empirically, by refactoring 97 AsyncTasks in 9 popular open-source Android projects. We evaluate A SYNC D ROID from three aspects. First, 45% of the AsyncTasks pass the refactoring preconditions, and with minor manual changes another 10% AsyncTasks can pass preconditions. This means the refactoring is highly applicable. Second, A SYNC D ROID changed 3386 SLOC in 77 files in total, determined that 148 variables flow into or escape from IntentService, moved 14 methods into IntentService, and marked 18 types as serializable. This task is very large and challenging to be performed manually, but A SYNC D ROID performs each refactoring in a few seconds. This shows that A SYNC D ROID can save developer effort. Third, we submitted 30 refactoring patches in 5 projects. 2 projects replied and considered our changes to be correct, and they accepted 9 refactorings. This shows A SYNC D ROID is valuable. RQ3: How do expert developers interpret the disparity in usage of async constructs? Answering this question can provide educational value for developers. We found that experts think AsyncTask is being overused at the expense of other enhanced async constructs, and many inexperienced Android developers do not know its problem. They also suggest AsyncTask should only be considered for short-running tasks (i.e., less than a second). They suggest that the current guides and examples of IntentService are not enough, and point out the need for refactoring tools to help unexperienced developers use and learn about the enhanced async constructs and the different style of communicating with the GUI. The tool and subjects for our study and evaluation are available at: http://mir.cs.illinois.edu/∼yulin2/asyncdroid/ II. BACKGROUND ON A NDROID An Android app consists of four types of components: activity, service, broadcast receiver and content provider. In this paper, we focus on the first three components. Activities contain GUI widgets and represent the GUI screens that are shown to users. Services do not provide GUI but perform invisible operations (e.g., playing music). Broadcast receivers provide a channel for activities and services to communicate. Inspired by the results of our formative study, we designed, developed, and evaluated A SYNC D ROID, an automated refactoring tool that transforms shared-memory into distributed-style communication in the context of Android async programming. A SYNC D ROID refactors AsyncTask into IntentService. We developed A SYNC D ROID as an Eclipse plugin, thus it offers all the convenience of a modern refactoring tool: it enables the user to preview and undo changes and it preserves formatting and comments. To use it the programmer only needs to select an AsyncTask instance, then A SYNC D ROID verifies that the transformation is safe, and rewrites the code if the preconditions are met. However, if a precondition fails, it warns the programmer and provides useful information that helps the programmer fix the problem. Similar to many other GUI frameworks such as Swing [13] and SWT [17], Android uses an event-driven model. Events in Android include lifecycle events (e.g., activity creation), user actions (e.g., button click, menu selection), sensor inputs (e.g., GPS, orientation change), etc. Developers define event handlers to respond to these events. For example, onCreate handler is a lifecycle event handler and is invoked automatically by the OS when an activity creation event occurs, while onClick handler of a button is invoked when user clicks the button. This paper makes the following contributions: Problem Description: To the best of our knowledge, we are the first to propose solving the generic problem of converting shared-memory into distributed-style communication through refactoring. We do this in the context of Android async programming. Android framework uses a single thread model to process events [3]. When an application is launched, the system creates a UI thread, in which it will run the application. This thread is in charge of dispatching UI events to appropriate widgets or lifecycle events to activities. It puts events into a single event queue, dequeues events, and executes event handlers. By default, all the event handlers defined in the above three components are processed by the UI thread one by one. Thus, if any handler executes CPU or IO bound operations such as network access, the UI thread will be blocked and no further events can be processed. This will lead to unresponsiveness. To avoid unresponsiveness, developers should exploit asynchrony and schedule long-running tasks on background threads. Android provides three major async constructs: AsyncTask, IntentService and AsyncTaskLoader. Formative study: To the best of our knowledge, this paper presents the first quantitative and qualitative study to (i) map the asynchronous landscape of Android, (ii) understand how developers retrofit asynchrony, and (iii) learn about barriers encountered by developers. Algorithms: We designed the analysis and transformation algorithms to address the challenges of refactoring from shared-memory communication (as used in AsyncTask) to distributed-style communication (as used in 2 GUI background thread AsyncTask B. OS/Library AsyncTask.execute onPreExecute GUI update doInBackground background task publishProgress GUI update CPU/IO operations onProgressUpdate onPostExecute GUI update (a) Where is AsyncTask code executing? GUI Broadcast Receiver Intent Service background thread OS/Library startService onHandleIntent registerBroadcast Receiver background task CPU/IO operations sendBroadcast GUI update onReceive (b) Where is IntentService code executing? Fig. 1: Flow of Android async constructs A. AsyncTask IntentService IntentService belongs to the Service component, but its encapsulated operations are executed in a background thread instead of UI thread. Figure 1(b) shows the flow of IntentService. Service is started when startService is invoked. Then onHandleIntent method is executed in a background thread. Unlike AsyncTask, IntentService uses a distributed-style programming to communicate with UI thread. To get the task result, the GUI that starts the service should register a broadcast receiver. After the task is finished, IntentService sends its task result via sendBroadcast method. Once the registered receiver receives (i.e., the GUI) this broadcast, its onReceive method will be executed on UI thread, so it can get the task result and update GUI. Figure 2(b) shows an equivalent implementation of LogActivity using IntentService. The background task from Fig. 2(a) is now put into onHandleIntent method (line 31). The result is wrapped by an Intent object, which is marshalled and sent via broadcast (lines 34, 35). Intent is analogous to a hash map whose key is a string and value is a serializable object (i.e., implements java.io.Serializable or android.os.Parcelable). It is the only medium through which different components (e.g., service and broadcast receiver) can exchange data. Finally, onReceive unwraps the result and updates the text view (line 21). Notice that to register a receiver, the developer should provide a filter (represented by a string) to specify which broadcast the receiver can receive. For example, line 2 defines a filter “FILTER”. Lines 8 and 29 use it to register receiver and send broadcast. Since IntentService is not affected by the destruction of the GUI objects that started it, it does not suffer from the problems introduced in Sec. I. Thus, it can be safely used for both short or long tasks. AsyncTask provides a doInBackground method for encapsulating asynchronous work. It also provides four event handlers which are run in the UI thread. The doInBackground and these event handlers share variables through which the background task can communicate with UI. Figure 1(a) shows the flow of AsyncTask. An AsyncTask is started by invoking execute method. UI thread first executes onPreExecute handler. Then doInBackground method is executed in a background thread. While the task is executing, it can report its progress to the UI thread by invoking publishProgress and implementing onProgressUpdate handler. Finally, UI thread executes the onPostExecute handler after doInBackground finishes. onPostExecute takes the task result as its parameter. Notice that user can also cancel an AsyncTask. If a task is canceled, onCancel handler will be executed instead of onPostExecute. C. AsyncTaskLoader AsyncTaskLoader is built on top of AsyncTask, and it provides similar handlers as AsyncTask. Unlike AsyncTask, AsyncTaskLoader is lifecycle aware: Android system binds/unbinds the background task with GUI according to GUI’s lifecycle. Thus, it can also solve the problems we mentioned in Sec. I. However, AsyncTaskLoader is introduced after Android 3.0, and it only supports two GUI components: activity and fragment. III. F ORMATIVE S TUDY OF A NDROID A SYNCHRONY Figure 2(a) shows a real-world example from owncloudandroid app, which is an Android client for a cloud server. LogActivity starts a LoadingLogTask at line 11. The task reads some files in doInBackground (lines 31, 32) and returns a string (line 35). onPostExecute takes this string and uses it to update a text view (line 21). Notice that LoadingLogTask is declared as a non-static inner class, so it holds a reference to LogActivity. We want to assess the state of practice async programming in open-source Android apps. To obtain a deep understanding of asynchronous programming practices in Android, we answer three research questions. We now answer each of these questions, by first presenting the methodology and corpus, and then the results. Though AsyncTask is an easy-to-use construct, it is ideally used for short tasks. Otherwise, the three problems introduced in Sec. I (memory leaks, lost results, wasted energy) can occur. To answer this question, we studied all async constructs provided by the standard Android libraries: AsyncTask, IntentService, AsyncTaskLoader and also the legacystyle Java Thread. RQ1: How do Android developers use asynchronous programming? 3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 1 2 3 4 private String mLogPath = FileStorageUtils.getLogPath(); 5 protected void onCreate() { 6 ... 7 LoadingLogTask task = new LoadingLogTask(view); 8 9 10 11 task.execute(); 12 } 13 private class LoadingLogTask extends AsyncTask { 14 private TextView textView; 15 private Exception exception; public LoadingLogTask(TextView view){ textView = view; } 16 17 public void onPostExecute(String result) { 18 19 20 if (exception == null) { 21 textView.setText(result); 22 } else Log.i(exception.getMessage()); 23 } 24 25 26 27 public String doInBackground(String[] args) { 28 29 30 try { 31 File file = new File(mLogPath); 32 ... 33 34 35 return text; 36 } catch (Exception e) { 37 exception = e; 38 39 40 return null; 41 }}}} public class LogActivity extends Activity { public class LogActivity extends Activity { public static final FILTER = "LogActivity_receiver"; private LoadingLogReceiver receiver; private String mLogPath = FileStorageUtils.getLogPath(); protected void onCreate() { ... receiver = new LoadingLogReceiver(view); this.registerReceiver(receiver, new IntentFilter(FILTER); Intent intent = new Intent(this, LoadingLogService.class); intent.putExtra("mLogPath", mLogPath); this.startService(intent); } private class LoadingLogReceiver extends BroadcastReceiver { private TextView textView; private Exception exception; public LoadingLogReceiver(TextView view){ textView = view; } public void onReceive(Context context, Intent intent) { String text = intent.getStringExtra("RV"); Exception exception = (Exception)intent.getSerializableExtra("exception"); if (exception == null) { textView.setText(text); } else Log.i(exception.getMessage()); }}} public class LoadingLogService extends IntentService { private String mLogPath; private Exception exception; public void onHandleIntent(Intent intent) { this.mLogPath = intent.getStringExtra("mLogPath"); Intent result = new Intent(LogActivity.FILTER); try { File file = new File(mLogPath); ... result.putExtra("exception", exception); result.putExtra("RV", text); sendBroadcast(result); } catch (Exception e) { exception = e; result.putExtra("exception", exception); result.putExtra("RV", null); sendBroadcast(result); }}} (a) Using AsyncTask (b) Using IntentService Fig. 2: Asynchronous code from owncloud-android app. onCreate method starts a background task to read a log file, and the result is shown in a TextView. (a) and (b) shows two semantic-equivalent implementations using AsyncTask and IntentService, respectively. Corpus-1. To collect representative Android apps, we chose Github [11]. To distinguish Android apps in Github, we first searched all apps whose README file contains the “Android” keyword. Because we want to analyze recently updated apps, we filtered for apps which have been modified at least once since July 2014. Then, we sorted all these apps based on their star count and gathered the top 500 apps. To make sure that these apps have Android projects, we check whether every app has at least one “AndroidManifest.xml” file, which every Android project must contain in its root directory. After all filters, our code corpus has 500 Android apps, comprising 4.69M nonblank, non-comment SLOC (as reported by SLOCCount [14]). the textual level, improves the accuracy in several ways. First, it is immune to noise generated by text that matches names of the async constructs (e.g., import statements, comments, variable names, etc.) but does not represent an instance of an async construct. Second, it correctly accounts for the ways in which developers instantiate async constructs: via anonymous inner classes (e.g., myAsyncTask = new AsyncTask(...)) and via class subtyping (e.g., class MyService extends IntentService. Results. Table I tabulates the usage statistics of async constructs. The three columns show the total number of construct instances, the total number of apps with instances of the construct, and the percentage of apps with instances of the construct. Methodology. We built a tool, A SYNC A NALYZER to automatically analyze the usage of async constructs in our corpus. A SYNC A NALYZER uses Eclipse API for syntactic analysis. It builds an abstract syntax tree (AST) for each source file and traverses ASTs to gather the usage statistics for the four async constructs. Doing the analysis at the level of ASTs and not at As we see from the table, AsyncTask is the most popular async construct in our corpus, based on the total number of instances. However, if we count the total number of apps that use at least one of these constructs, then the legacy-style Thread is the most popular, despite the fact that Android already provides three special async constructs. AsyncTaskLoader and IntentService are not as popular as the other two. TABLE I: Usage of async constructs in the Corpus-1 # Instances # App App% AsyncTask 938 97 19% Thread 655 110 22% IntentService 182 30 6% AsyncTaskLoader 118 14 3% RQ2: How do Android developers retrofit asynchrony into existing apps? Next we analyze how developers introduce async constructs into their apps. We want to determine whether developers introduced async constructs when (i) implementing new features 4 TABLE II: How developers introduce AsyncTask and IntentService in the Corpus-2 Type TABLE III: How developers introduce AsyncTask and AsyncTaskLoader in the Corpus-3 # Instances Type # Instances Newly added AsyncTask 277 Newly added AsyncTask 73 Refactor sequential code to AsyncTask 103 Refactor sequential code to AsyncTask 24 Refactor Thread to AsyncTask Newly added IntentService 18 Refactor Thread to AsyncTask 2 205 Newly added AsyncTaskLoader 15 Refactor sequential code to IntentService 13 Refactor sequential code to AsyncTaskLoader Refactor Thread to IntentService 18 Refactor AsyncTask to AsyncTaskLoader Refactor AsyncTask to IntentService 9 Refactor AsyncTaskLoader to IntentService 5 Refactor Thread to AsyncTaskLoader 3 10 3 programming. In StackOverflow, users are sorted by their points that they received from their answers for questions which are associated with some tags. We contacted the top 10 users for the “android-async” tag and these 10 people are the ones who answered the questions related to Android async programming most. On average, each of them answered 2095 questions on StackOverflow. We got replies from 5 of them, including the author of a popular Android programming book [40]. (i.e., asynchrony was added to a new program element when writing code from scratch), (ii) refactoring from existing sequential code, (iii) refactoring from another existing async construct. In order to be able to detect transitions between basic and enhanced async constructs, we need to find projects where developers are aware that the enhanced constructs exist. Thus, we use 2 different corpora to study IntentService and AsyncTaskLoader, respectively: Results. We asked three questions and summarized the experts’ answers below: Corpus-2. We collected 93 random open-source Android apps from Github, comprising 1.54M SLOC, which use both AsyncTask and IntentService constructs in their latest snapshot. Q1) Why are there still lots of legacy-style Thread uses even though Android provides three dedicated async constructs? First, Thread construct has been around since the beginning and many Android developers formerly developed Java apps. Developers are very familiar with Thread and they do not have time to learn something new, thus they continue using it. Second, Thread is suitable for other scenarios, such as parallelism and scheduled tasks. Corpus-3. We collected 18 random open-source Android apps, comprising 0.24M SLOC, which use both AsyncTask and AsyncTaskLoader constructs in their latest snapshot. Methodology. In order to identify transitions, we study not only the latest version of the code, but also the first version where developers introduce async constructs. To do this, we automatically searched the commit history of our corpora through Gitective API [10], identified the commits that add import statements to AsyncTask, AsyncTaskLoader, or IntentService. After automatically finding commits that introduce these async constructs, we manually inspected the versions before and after such commits in order to understand how these async constructs are introduced. Q2) Why are there many more AsyncTask uses than the other two enhanced constructs even though AsyncTask may lead to memory leaks, lost task results, and wasted energy? They all agree that AsyncTask “is being overused” at the expense of the other two enhanced constructs. As a main reason, they invoke a historical account “AsyncTask was advertised to the developers a lot in Android documentation” and it “got a lot of good press early on”. On the other hand, they thought “many developers coming from desktop do not realize the async nature of the Android memory management”. They also mention that AsyncTaskLoader has been around only for a short time and is harder to implement, and Google has not provided production-level examples of code that use IntentService and AsyncTaskLoader. Results. Tables II and III show how AsyncTask, IntentService, and AsyncTaskLoader are introduced. The results show that in many cases developers refactor sequential code to AsyncTask. This observation confirms our previous findings [36]. However, the refactorings for IntentService and AsyncTaskLoader mostly come from other async constructs. This shows the following code evolution scenario: developers first convert sequential code to AsyncTask, and those that continue to evolve the code for better use of asynchrony refactor it further into IntentService or AsyncTaskLoader. As a guidance on Android async programming, they suggest that AsyncTask or Thread should only be considered for short tasks (i.e., less than one second). For the work that will take more than a second, developers should use IntentService. Q3) Do you think that developers can benefit from a refactoring tool from AsyncTask to IntentService? RQ3: How do expert developers interpret the disparity in usage of async constructs? They concluded that the technical challenges make the automation really hard: “it would be a very difficult task, so the end solution may appear very complicated”, “that would be quite a challenge to do automatically”. One also said that “it may help beginner, but senior developers still like using their To shed light into this question, we conducted a survey with expert Android developers. Methodology. To find expert developers, we used StackOverflow [15], which is the pioneering Q&A website for 5 Where to Register the Receiver. In order to receive the computation result from the channels, the GUI needs to register a BroadcastReceiver. A naive approach is to register at the original call site where the AsyncTask is created. For example, in Fig. 2(a), the task is created in onCreate at line 7. While using IntentService in Fig. 2(b), the receiver is registered at the same place in onCreate (line 8). This approach only works when the original call site is already in a lifecycle event handler, such as onCreate method. Lifecycle events are guaranteed to be triggered by OS during GUI recreation, so the receiver can be registered automatically. preferred way of writing async” and another said “it would have to be very compelling for users to take their existing code and change it - especially to something they do not already understand”. IV. R EFACTORING A SYNC TASK TO I NTENT S ERVICE Based on our findings from Sec. III, developers tend to choose AsyncTask for Android async programming. However, AsyncTask is not fit for long-running tasks, where developers should use IntentService or AsyncTaskLoader. Inspired by these findings, we propose A SYNC D ROID, an automated refactoring tool that transforms shared-memory into distributed-style communication in the context of Android async programming. A SYNC D ROID refactors existing AsyncTask into IntentService. It helps developers migrate the inappropriately used AsyncTasks to IntentServices. Additionally, by looking at transformations performed (e.g., using Eclipse’s preview refactoring feature), developers can educate themselves on how to transform between AsyncTasks to IntentServices. However, if the call site is not in a lifecycle event handler, the receiver cannot be registered unless the event is triggered again after GUI recreation. For example, the call site can be in the onClick listener of a button, so the receiver can only be registered when the user clicks the button. If the GUI containing the button is recreated while the background task is running, the recreated GUI cannot receive the broadcast unless the button is clicked again. Thus, the developer also needs to infer where to register BroadcastReceiver during the refactoring. This is a non-trivial insight for developers, because online documents only show basic Android asynchronous programming scenarios, where this is not a concern. A. Refactoring Challenges There are three main challenges that make it hard to execute the refactoring quick and flawlessly by hand. First, the developer needs to determine which objects should be transferred into IntentService and BroadcastReceiver, and how to transfer them. Second, the developer should establish channels to enable communication between IntentService and GUI. Third, the developer must register the receiver properly in order to receive the computation result from the established channel. B. The Canonical Form of AsyncTask Code and Refactoring Preconditions A key insight in designing refactorings is that there is a canonical form for input code [30], [42]. This canonical form adheres to the preconditions of the refactoring, so that the result of the transformation is indeed correct. This means that if the input code is not in canonical form, it is necessary to transform into canonical form before performing the refactoring. A SYNC D ROID has several preconditions, which together dictate the canonical form which the source code must adhere to for a successful transformation: Transfer Objects from/to IntentService. As shown in Sec. II, the non-local objects required by AsyncTask are passed as method arguments or can be directly accessed as fields from the outer class. However, the objects that flow into and escape from IntentService have to be wrapped and sent via an Intent object. Similar to distributed-style programming, objects transferred in this way are required to be serializable [2]. P1: All variables that flow into or escape from doInBackground are or can be marked as serializable. This is required because such variables need to be transferred to IntentService and BroadcastReceiver via marshalling/unmarshalling. For example, at line 31 in Fig. 2(a), field mLogPath flows into doInBackground method. Thus, it should be transferred to IntentService during refactoring (line 10 in Fig. 2(b)). Determining objects transfer requires a nontrivial inter-procedural analysis of the code: the developer must trace (i) the call graph to figure out which objects flow into IntentService and BroadcastReceiver, and (ii) type hierarchy to check if the objects can be serialized. P2: All the methods invoked in doInBackground should also be accessible by IntentService. Because most AsyncTasks are declared as non-static inner classes, they can call methods from the outer class. Since IntentService is not an inner class, it needs to be able to call the same set of methods from the outer class, so their visibility needs to be appropriate. Establish Channels for Communication. AsyncTask provides four handlers that enable developers to interact with GUI. Background task and handlers exchange data by accessing the shared memory. However, IntentService sends broadcast to BroadcastReceiver to communicate with GUI. Thus, the developer needs to rewire the channels of communication. To achieve this, one must split AsyncTask into IntentService and BroadcastReceiver. Splitting an AsyncTask includes moving the related fields and methods into IntentService and BroadcastReceiver, which requires to trace the call graph. Additionally, the developer has to write extra code for sending broadcast, which makes the refactoring more tedious. P3: The refactored task is directly extended from AsyncTask and is not subclassed. This precondition prevents the refactoring from breaking the inheritance relation and affecting other AsyncTasks that are not refactored in the type hierarchy. P4: An AsyncTask instance is only used when invoking AsyncTask.execute. For example, if a task instance is used as a method argument or return value, A SYNC D ROID halts the refactoring to avoid changing the design contract of the method. On the other hand, AsyncTask defines some methods that are not supported by IntentService (e.g., AsyncTask.cancel). If these methods are invoked on the task instance, A SYNC D ROID halts the refactoring. 6 we never find a case in practice where these two types of IV are modified. A reasonable explanation is that modifying them in a background thread can introduce data races. Figure 2(a) is a valid example of a target program that meets all these preconditions, thus it can be refactored by A SYNC D ROID. We will see in Sec. V how many real-world programs readily meet these preconditions. As mentioned in Sec. IV-A, the objects in the IV and OV set are required to be serializable. A SYNC D ROID traverses the type hierarchy and checks the serializability of an variable type based on its definition [12]: a type is serializable if it implements java.io.Serializable and all of its fields’ types are serializable, unless the field is transient. A SYNC D ROID also refactors a type to implement java.io.Serializable if its fields conform to the definition but it has not implemented yet. Note that when refactoring a type to be serializable, A SYNC D ROID also checks the serializability of all its subtypes to guarantee the transformation is safe, and it only refactors the type defined in source code, not libraries. If any of the IV and OV are not serializable or cannot be refactored, the refactoring fails precondition P1. C. The Refactoring Algorithm A SYNC D ROID takes the following steps to refactor an AsycnTask to IntentService. Analyzing Transferred Objects. Since doInBackground and onHandleIntent are semantic-equivalent methods that enclose background task, A SYNC D ROID needs to analyze doInbackground to determine which objects should be transferred. We define the Target Class, Incoming Variables and Outgoing Variables for IntentService as following: Definition 1 (Target Class (T C)): The top-level or static inner class that creates and starts the AsyncTask. Generating and Starting IntentService. First, for the target AsyncTask, A SYNC D ROID creates a corresponding IntentService class. The method body of onHandleIntent is moved from doInBackground. Unlike AsyncTask, IntentService class cannot be a nonstatic inner class. Thus, A SYNC D ROID creates it as an independent class. A SYNC D ROID creates a field for each variables in IV and OV. A SYNC D ROID adds statements to unwrap objects in IV from Intent at the beginning of onHandleIntent (line 28 in Fig. 2(b)) . At every exit of doInBackground, A SYNC D ROID creates an Intent to carry OV, and sends it via broadcast (lines 33 to 35 and 38 to 40 in Fig. 2(b)). Definition 2 (Incoming Variables (IV)): The set of nonlocal variables flow into doInBackground, which have to be transferred to IntentService, is: FT C ∪ Ftask ∪ Argstask ∪ LVT CM where: • FT C is the set of T C’s fields when the AsyncTask is a non-static inner class of T C • Ftask is the set of AsyncTask’s fields that are initialized in its constructors or onPreExecute handler • Argstask are the arguments of AsyncTask.execute method Second, since doInBackground can invoke methods defined in AsyncTask or T C’s methods, A SYNC D ROID copies such methods into IntentService class. Note that A SYNC D ROID moves such methods instead of copying if doInBackground is the only caller. However, if any of such methods are in library code and cannot be copied, the refactoring fails P2. • LVT CM is the set of final local variables declared in the T C’s method where the task is created, when the AsyncTask is an anonymous inner class of T C Notice that collecting IV requires inter-procedural analysis since doInBackground may invoke other methods defined in T C or the AsyncTask. Finally, A SYNC D ROID rewrites the call sites of AsyncTask.execute into startService. This includes creating the Intent object to wrap the IV (lines 9-11 in Fig. 2(b)). set of Definition 3 (Outgoing Variables (OV)): The variables that escape from doInBackground and need to be transferred from IntentService to BroadcastReceiver, is: FTMC • ∪ M Ftask Notice that in Android, starting a service or sending a broadcast requests a Context object. A SYNC D ROID checks if (i) T C itself is a subclass of Context and (ii) T C contains a visible Context field or local variable, or a visible method that returns a Context object. A SYNC D ROID uses such Context if there is any, otherwise the refactoring stops. ∪ RV where: FTMC is the set of T C’s fields that are modified in doInBackground method M • Ftask is the set of AsyncTask’s fields that are modified in doInBackground method and used in onPostExecute Creating and Registering Receiver. AsyncTask communicates with GUI through handlers. However, to receive task result from IntentService, the developer needs to establish a channel by registering a BroadcastReceiver on GUI. A SYNC D ROID rewrites the target AsyncTask into BroadcastReceiver class. It keeps all the fields, constructors and handlers defined in AsyncTask, and rewrites onPostExecute handler into BroadcastReceiver.onReceive (lines 17 in Fig. 2(b)). A SYNC D ROID also inserts statements at the beginning of onReceive to unwrap OV and writes them back to corresponding variables (lines 18, 19 in Fig. 2(b)). • RV is the return value of doInBackground method An example of OV is the return value text and a field M exception in Fig. 2(a) (lines 35, 37). FTMC and Ftask are OV because IntentService and GUI holds and operates on different copies of objects due to (de)serialization. They should be written back in BroadcastReceiver otherwise the modifications are lost. Note that there is no way to write back modified incoming LVT CM or Argstask due to the communication mechanism of IntentService. However, 7 As discussed in Sec. IV-A, to avoid losing task result during GUI destroying and recreation, the receiver should be registered in lifecycle event handlers. A SYNC D ROID declares the receiver as a field of T C (line 3 in Fig. 2(b)). It tries to move the receiver creation and registration into T C’s lifecycle event handlers unless they are already there. The following example shows an AsyncTask that executes in a button’s onClick listener. A SYNC D ROID register the receiver in onCreate lifecycle handler during refactoring instead of in the onClick listener: TABLE IV: Nine popular Android projects from Github. Project Name void onCreate() { button.setOnClickListener() {() −> { new MyAsyncTask(...).execute();}} } SLOC # AsyncTask # IntentService owncloud-android open311-android prey-android-client SMSSync opentripplanner UltimateAndroid AntennaPod WhatAndroid TextSecure 54918 6642 15361 16706 11766 228154 38430 23643 40819 6 5 8 10 7 10 24 20 18 0 0 1 2 0 0 0 0 0 Total 436439 102 3 ⇓ BroadcastReceiver receiver; void onCreate() { receiver = new MyBroadcastReceiver(...); registerReceiver(receiver, ...); button.setOnClickListener() {() −> {startService(...);}} } D. The Refactoring Implementation We have implemented the refactoring as a plugin in the Eclipse IDE, on top of Eclipse JDT [8] and refactoring engine [7]. To use A SYNC D ROID, the developer selects the doInBackground method in the AsyncTask she wants to transform, and then chooses C ONVERT T O I NTENT S ERVICE option from the refactoring menu. Note that a T C can have multiple lifecycle event handlers. A SYNC D ROID registers the receiver in the handler that is invoked first by the system (e.g., onCreate). A receiver can be moved if and only if (i) the T C contains lifecycle event handlers, (ii) all variables transferred to the receiver are still visible to it after moving, and (iii) the variables used by receiver’s constructor are not redefined in other lifecycle event handlers. Rule (ii) guarantees syntax correction while rule (iii) preserves the semantics of the refactoring. A SYNC D ROID raises a warning when a receiver cannot be moved. V. E VALUATION To empirically evaluate whether A SYNC D ROID is useful, we answer the following evaluation questions. EQ1. Applicability: How applicable is the refactoring? EQ2. Effort: How much programmer effort is saved by A SYNC D ROID when refactoring? EQ3. Accuracy and Value: How accurate is A SYNC D ROID when performing a refactoring? Do developers think that the refactorings performed by A SYNC D ROID are useful? A filter is required when registering receiver. The filter specifies which broadcast a receiver can receive. A SYNC D ROID concatenates T C class name and receiver name as filter name, and uses it to register receiver and send broadcast (lines 2, 8 and 29 in Fig. 2(b)). Dealing with other AsyncTask handlers. In addition to onPostExecute, AsyncTask provides three other handlers. Note that the generated BroadcastReceiver keeps all these three handlers. For onPreExecute, A SYNC D ROID inserts an invocation to this handler before starting the service. A. Experimental Setup For onProgressUpdate, A SYNC D ROID first rewrites the call site of publishProgress into sendBroadcast, with the filter set to “ProgressUpdate”: Table IV provides statistics about these projects. We report the size (in SLOC), the number of AsyncTask and IntentService instances that are used in each project. To answer the above questions, we apply A SYNC D ROID on nine popular Github open-source Android projects. We selected projects that use AsyncTask predominantly. void doInBackground(...) { publishProgress(arg); } For each project, we applied the A SYNC D ROID to every AsyncTask, except for the ones that have already been used in Service or retained Fragment. The lifecycle of such AsyncTasks is independent of GUI’s lifecycle, so the they do not suffer from the problems described in Sec. I. ⇓ void onHandleIntent(...) { intent.setAction(”ProgressUpdate”); intent.putExtra(”taskProgress”, arg); sendBroadcast(intent); } Then in onReceive, A SYNC D ROID adds a branch to intercept the “ProgressUpdate” broadcast, and invokes onProgressUpdate: We recorded several metrics for each refactoring. To measure the applicability, we counted how many instances met the refactoring preconditions and thus can be refactored. We also analyzed the reasons why the remaining instances cannot be refactored by A SYNC D ROID. To measure refactoring effort, we recorded the number of input and output variables (IV, OV), serialized types, moved/copied methods and moved receivers. We also counted the number of files and SLOC that are changed. To verify the accuracy and value, we manually examine the correctness of all the refactored code. We also sent 30 refactorings in 5 projects to developers and let them judge the correctness and usefulness. void onProgressUpdate(...) {...} void onReceive(Context context, Intent intent) { ... // code from onPostExecute } ⇓ void onProgressUpdate(...) {...} void onReceive(Context context, Intent intent) { if(intent.getAction().equals(”ProgressUpdate”)) { ...; onProgressUpdate(...); } else ... // code from onPostExecute } A SYNC D ROID ignores onCancelled handler, since Android does not support canceling IntentService. Tasks that invoke AsyncTask.cancel fails P4. 8 TABLE V: Results of applying A SYNC D ROID to AsyncTask in nine Android projects. # Task Objects 4 0 1 6 4 2 15 6 3 1 0 0 0 1 2 4 0 0 2 0 0 0 0 2 16 1 0 6 6 11 0 8 6 8 11 25 5 10 9 1 8 6 8 10 10 1 3 5 0 4 0 1 0 0 0 10 2 0 3 0 2 0 1 2/0 3/0 4/2 1/0 0/10 4/0 4/3 9/0 3/0 3 11 10 1 14 7 11 9 11 193 395 392 41 679 310 418 411 547 3 5 8 1 10 8 8 9 10 Total 44 10 43 41 7 21 81 67 14 18 30/15 77 3386 62 SLO Mod C . 3 0 0 6 3 4 16 8 3 # OV File s Mod . 2 0 1 0 2 1 4 0 0 # IV Mov unm ed & Rec oved eive rs 1 5 7 1 2 5 4 9 10 P4 Seri a Typ lized es owncloud-android open311-android prey-android-client SMSSync opentripplanner UltimateAndroid AntennaPod WhatAndroid TextSecure P2 Mov Met ed hod s P1 d Fail ed Effort Con Pass ditional ed Applicability Pass e Project Name IV: incoming vars; OV: outgoing vars; P1: all IV and OV can be serializable; P2: all methods invoked by doInBackground are accessible in IntentService; P4: AsyncTask is only used when invoking AsyncTask.execute. source-to-source transformation tool like A SYNC D ROID cannot transform third-party binary code. B. Results Table V shows the result of applying A SYNC D ROID on the AsyncTasks in our corpus of 9 Android projects. Preconditions P2 and P4 are violated mainly due to methods cancel or executeOnExecutor that are invoked either in doInBackground (thus failing P2) or on the task instance (thus failing P4). Since these methods are specific to AsyncTask and IntentService does not support them, A SYNC D ROID cannot transform those cases. For P3, we only find one violation in WhatAndroid, so we do not show them in Table V due to lack of space. Applicability. We totally refactored 97 AsyncTasks in the nine projects. Columns 2 and 4 show the number of instances that pass and fail the refactoring preconditions. There are 44 AsyncTasks that pass the preconditions, while 43 fail the preconditions. This is not a limitation of A SYNC D ROID, but such cases can not be converted from shared-memory to distributed-style. Column 3 shows another 10 AsyncTasks that fail the preconditions. However, these instances can be refactored into canonical form with other well-known refactorings (such as demoting fields to local variables) so that A SYNC D ROID can refactor them. We show these instances in the “conditional pass” column. In terms of applicability, A SYNC D ROID successfully refactored 45.3% AscynTasks directly in nine projects. There are 10.3% AscynTasks that can also be refactored after converting them to canonical form. This shows that A SYNC D ROID has a high level of applicability. Effort. We estimate the effort based on the 54 AsyncTasks that pass or conditional pass the preconditions. In the last column, we show the number of task instances that are created for the 54 AsyncTasks. 62 task instances are created in total, which means most AsyncTasks are used only at one place. This observation confirms our previous study [36]: developers tend to tightly bind an AsyncTask to only one GUI component. We discovered two common transformations that convert code into canonical form. First, an unserializable object contained in IV but not in OV, can be converted into a local variable in doInBackground as long as it is only used by doInBackground: UnserializableObject object = new UnserializableObject(...); void doInBackground(...) { object.method(); } ⇓ void doInBackground(...) { UnserializableObject object = new UnserializableObject(...); object.method(); } Columns 8 and 9 show the number of IV and OV for each project. For the 54 AsyncTasks, there are 81 IV and 67 OV. Detecting them needs inter-procedural analysis. Moreover, wrapping them into Intent object is also tedious. Second, an AscynTask that is executed on a ThreadPool, can be changed to execute on a plain thread since IntentService does not support ThreadPools: Column 10 shows the methods that need to be moved or copied into IntentService. We find 14 methods that should be put into IntentService. Note that searching these methods also needs inter-procedural analysis. Column 11 shows the number of types that are refactored to be serializable. On average, each refactoring marks 0.33 types as serializable. However, checking serializability is tedious since it requires traversing the type hierarchy for each field. AsyncTask task = new AsyncTask() {...}; task.executeOnExecutor(...); ⇓ AsyncTask task = new AsyncTask() {...}; task.execute(...); For refactorings that conditional-pass or fail the preconditions, we analyzed which preconditions they violate. Columns 5 to 7 shows the number of instances that fail P1, P2 and P4. Note that one refactoring can violate multiple preconditions. The result shows most failed refactorings violate P1. The main reason is that the unserializable types in IV or OV are declared in third-party libraries (such as network or database). A Column 12 shows the number of BroadcastReceivers that are moved into lifecycle event handlers by A SYNC D ROID (left side of slash), and that have to be moved but A SYNC D ROID 9 cannot move (right side of slash). Notice that for each task instance, A SYNC D ROID creates a corresponding receiver. Therefore, it creates 62 receivers in total: 30 are moved, 15 cannot be moved, and the remaining 18 are already in lifecycle event handlers. For the 15 unmoved receivers, GUI component can lose task result if GUI destroying and recreation occurs during task running, thus A SYNC D ROID raises a warning. in modern software. Their result shows concurrency and performance related bugs can have a severe impact on software. Bavota et al. [23] investigate to what extent refactoring activities induce faults. There are also several empirical studies [26], [29], [31], [43] on the usage of libraries or programing language constructs. Dyer et al. [28] analyzes 31k open-source Java projects to find uses of new Java language features over time. Buse et al. [25] propose an automatic technique for synthesizing API usage examples and conduct a study on the generated examples. Our previous work [35], [41] studies the misuses of concurrent constructs in Java and C#. Our formative study on usage of async constructs is similar with other studies in the literature, but on different topics. In this work, we study how developers use Android async constructs. Columns 13 and 14 show the number of files and SLOC that are changed during the 54 refactorings. On average, each refactoring changes 1.43 files and 63 SLOC. A SYNC D ROID helps developers change several SLOC, and such changes are non-trivial. Thus, we conclude that A SYNC D ROID can save developers’ effort. Accuracy and Value. By manually examining the 54 refactored instances applied by A SYNC D ROID, we determined that no compilation errors were introduced and the original semantics of AsyncTask are preserved. Refactoring for concurrency, parallelism and asynchrony. The refactoring community has been recently pushing refactoring technology beyond its classic realm (i.e. in improving software design) into improving non-functional qualities such as performance through parallelism and concurrency. Schafer et al. [45] propose a refactoring for replacing Java built-in locks with more flexible locks. Wloka et al. [47] present a refactoring for replacing global state with thread local state. Schafer et al. [44] examine whether classic refactorings can be safely applied to concurrent programs. Our group implemented several implemented several concurrency-related refactorings to improve throughput [27], [32], [46]. Our previous work [36] presents a refactoring for Android developers to extract synchronous code from UI thread into async code that inverts the flow of control. In this work, we go one step further and investigate a new scientific challenge: converting between shared-memory communication with the UI into a distributedstyle as encompassed in two Android async constructs. We also submitted 30 refactorings in 5 projects to developers through Github pull request. Given the large size of changes in the patches that we submitted (on average a patch touching 10 files with 403 additions and 210 deletions), we expected that developers might not reply - as previous studies [35], [41] show that open-source developers are more likely to respond to small patches. Despite this, by May 2015, we received replies from 2 projects. WhatAndroid [18] developers accepted the 9 refactorings we submitted by saying: “this is an interesting set of changes, AsyncTask can definitely be a pain to deal with” and “these tasks are a good fit for migration to IntentServices and I will migrate over to IntentServices”. AntennaPod [5] developers said their AsyncTasks are short: “most of our tasks read or write data from the database and should finish well under 100ms”. They think AsyncTasks work fine for their shortrunning tasks while IntentService makes the code more verbose. This shows that A SYNC D ROID can produce accurate and valuable results. VI. Compiling shared-memory to distributed-memory. Several compiler techniques [20]–[22], [38], [50] have attempted to translate shared-memory program to distributed-memory program. However, these techniques target high performance distributed computing. In our work, we presented a refactoring from a shared-memory construct to a distributed-style construct in the context of Android asynchrony. R ELATED WORK Performance analysis and testing for mobile apps. Liu et al. [37] empirically study performance bug patterns in Android apps, and conclude that executing long-running operations in main thread is the main culprit. Berardinelli et al. [24] introduce a framework for modeling and analyzing the performance of context-aware mobile software systems. Arijo et al. [19] propose a model-based approach to analyze the performance of mobile apps, in which they represent state changes by graph transformation. Muccini et al. [39] analyze the challenges in testing mobile apps, including performance and memory testing. Lillack et al. [34] propose an approach to track load-time configuration for Android apps, which can help with tuning performance of Android apps. Yan et al. [48] propose a test generation approach to detect memory leaks for Android apps. However, our work is complementary to previous approaches: we assume that developers have already used the above techniques to detect responsiveness problems in their apps, and now we enable developers to fix these problems via refactoring for async programming. VII. C ONCLUSIONS Asynchronous execution of long-running tasks is crucial for the now ubiquitous mobile and wearable apps. Despite significant efforts to educate Android app developers on how to use async programming, developers can improperly use the primary construct, AsyncTask, which can lead to memory leaks, lost results, and wasted energy. In this paper we take stake of the usage of async constructs in a corpus of 611 widely-used Android apps. We discovered that developers refactor their sync code into AsyncTask, and some go further into using safer (but more complex) async constructs. To aid developers when converting to these constructs, we designed, implemented, and evaluated A SYNC D ROID. It is a refactoring that converts from AsyncTask which uses a shared-memory style of communication to IntentService which uses a distributed style of communication. Our empirical evaluation shows that A SYNC D ROID is applicable and accurate, and it saves effort. Developers already accepted several refactorings generated by A SYNC D ROID, which shows that it is valuable. Empirical study on concurrency, refactoring and API usage. Li et al. [33] study and categorize bug characteristics 10 VIII. ACKNOWLEDGMENTS [26] O. Callaú, R. Robbes, E. Tanter, and D. Röthlisberger, “How developers use the dynamic features of programming languages: The case of Smalltalk,” in Proceedings of the 8th Working Conference on Mining Software Repositories, ser. MSR ’11, 2011, pp. 23–32. [27] D. Dig, J. Marrero, and M. Ernst, “Refactoring sequential Java code for concurrency via concurrent libraries,” in Proceedings of the International Conference on Software Engineering, ser. ICSE ’09, 2009, pp. 397–407. [28] R. Dyer, H. Rajan, H. A. Nguyen, and T. N. Nguyen, “Mining billions of AST nodes to study actual and potential usage of Java language features,” in Proceedings of the 36th International Conference on Software Engineering, ser. ICSE 2014, 2014, pp. 779–790. [29] M. Grechanik, C. McMillan, L. DeFerrari, M. Comi, S. Crespi, D. Poshyvanyk, C. Fu, Q. Xie, and C. Ghezzi, “An empirical investigation into a large-scale java open source code repository,” in Proceedings of the 2010 ACM-IEEE International Symposium on Empirical Software Engineering and Measurement, ser. ESEM ’10, 2010, pp. 11:1–11:10. [30] W. G. Griswold, “Program restructuring as an aid to software maintenance,” Ph.D. dissertation, University of Washington, Seattle, WA, USA, 1992. [31] S. Karus and H. Gall, “A study of language usage evolution in open source software,” in Proceedings of the 8th Working Conference on Mining Software Repositories, ser. MSR ’11, 2011, pp. 13–22. [32] F. Kjolstad, D. Dig, G. Acevedo, and M. Snir, “Transformation for class immutability,” in Proceedings of the International Conference on Software Engineering, ser. ICSE ’11, 2011, pp. 61–70. [33] Z. Li, L. Tan, X. Wang, S. Lu, Y. Zhou, and C. Zhai, “Have things changed now?: An empirical study of bug characteristics in modern open source software,” in Proceedings of the 1st Workshop on Architectural and System Support for Improving Software Dependability, ser. ASID ’06, 2006, pp. 25–33. [34] M. Lillack, C. Kästner, and E. Bodden, “Tracking load-time configuration options,” in Proceedings of the 29th ACM/IEEE International Conference on Automated Software Engineering, ser. ASE ’14, 2014, pp. 445–456. [35] Y. Lin and D. Dig, “Check-then-act misuse of Java concurrent collections,” in Proceedings of the International Conference on Software Testing, Verification and Validation, ser. ICST ’13, 2013, pp. 164–173. [36] Y. Lin, C. Radoi, and D. Dig, “Retrofitting concurrency for android applications through refactoring,” in Proceedings of the 22Nd ACM SIGSOFT International Symposium on Foundations of Software Engineering, ser. FSE 2014, 2014, pp. 341–352. [37] Y. Liu, C. Xu, and S. Cheung, “Characterizing and detecting performance bugs for smartphone applications,” in Proceedings of the International Conference on Software Engineering, ser. ICSE ’14, 2014, pp. 1013– 1024. [38] S.-J. Min and R. Eigenmann, “Optimizing irregular shared-memory applications for clusters,” in Proceedings of the 22Nd Annual International Conference on Supercomputing, ser. ICS ’08, 2008, pp. 256–265. [39] H. Muccini, A. Di Francesco, and P. Esposito, “Software testing of mobile applications: Challenges and future research directions,” in Proceedings of the 7th International Workshop on Automation of Software Test, ser. AST ’12, 2012, pp. 29–35. [40] M. Murphy, The Busy Coder’s Guide to Android Development. CommonsWare, 2009. [41] S. Okur, D. Hartveld, D. Dig, and A. Deursen, “A study and toolkit for asynchronous programming in C#,” in Proceedings of the International Conference on Software Engineering, ser. ICSE ’14, 2014, pp. 1117– 1127. [42] W. F. Opdyke, “Refactoring object-oriented frameworks,” Ph.D. dissertation, University of Illinois at Urbana-Champaign, Champaign, IL, USA, 1992. [43] C. Parnin, C. Bird, and E. Murphy-Hill, “Adoption and use of Java generics,” Empirical Softw. Engg., vol. 18, no. 6, pp. 1047–1089, Dec. 2013. [44] M. Schäfer, J. Dolby, M. Sridharan, E. Torlak, and F. Tip, “Correct refactoring of concurrent Java code,” in Proceedings of the 24th European Conference on Object-oriented Programming, ser. ECOOP’10, 2010, pp. 225–249. [45] M. Schäfer, M. Sridharan, J. Dolby, and F. Tip, “Refactoring Java programs for flexible locking,” in Proceedings of the International Conference on Software Engineering, ser. ICSE ’11, 2011, pp. 71–80. We would like to thank Michael Hilton, Mihai Codoban, Kendall Bailey, Shane McKee and Sruti Srinivasa for their feedback on earlier versions of this paper. This research is partly funded through NSF CCF-1439957 and CCF-1442157 grants, a SEIF award from Microsoft, and a gift grant from Intel. R EFERENCES [1] “Activitys, Threads and Memory Leaks,” May 2015, http://www. androiddesignpatterns.com/2013/04/activitys-threads-memory-leaks. html. [2] “Android Intents and Intent Filters,” May 2015, http://developer.android. com/guide/components/intents-filters.html. [3] “Android Processes and Threads,” May 2015, http://developer.android. com/guide/components/processes-and-threads.html. [4] “Android’s AsyncTask,” May 2015, http://steveliles.github.io/android s asynctask.html. [5] “Antennapod repository.” May 2015, https://github.com/AntennaPod/ AntennaPod. [6] “The dark side of AsyncTask,” May 2015, http://bon-app-etit.blogspot. com/2013/04/the-dark-side-of-asynctask.html. [7] “Eclips Refactoring Engine,” May 2015, https://www.eclipse.org/articles/ Article-LTK/ltk.html. [8] “Eclipse Java development tools (JDT),” May 2015, http://www.eclipse. org/jdt/. [9] “Gartner.” May 2015, http://www.gartner.com/newsroom/id/2153215. [10] “GiTective,” May 2015, https://github.com/kevinsawicki/gitective. [11] “GitHub,” May 2015, https://github.com. [12] “Java Serializability,” May 2015, http://docs.oracle.com/javase/1.5.0/ docs/guide/serialization/spec/serial-arch.html. [13] “JDK Swing Framework,” May 2015, http://docs.oracle.com/javase/6/ docs/technotes/guides/swing/. [14] “SLOCCount,” May 2015, http://www.dwheeler.com/sloccount/. [15] “Stack Overflow.” May 2015, http://stackoverflow.com. [16] “Tablet Sales.” May 2015, http://www.gartner.com/newsroom/id/ 2954317. [17] “The SWT Toolkit,” May 2015, http://eclipse.org/swt/. [18] “Whatandroid repository.” May 2015, https://github.com/Gwindow/ WhatAndroid. [19] N. Arijo, R. Heckel, M. Tribastone, and S. Gilmore, “Modular performance modelling for mobile applications,” in Proceedings of the 2nd ACM/SPEC International Conference on Performance Engineering, ser. ICPE ’11, 2011, pp. 329–334. [20] P. Banerjee, J. Chandy, M. Gupta, J. Holm, A. Lain, D. Palermo, S. Ramaswamy, and E. Su, “The paradigm compiler for distributedmemory message passing multicomputers,” IEEE Computer, vol. 28, pp. 37–47, 1994. [21] A. Basumallik and R. Eigenmann, “Towards automatic translation of openmp to mpi,” in Proceedings of the 19th Annual International Conference on Supercomputing, ser. ICS ’05, 2005, pp. 189–198. [22] ——, “Optimizing irregular shared-memory applications for distributedmemory systems,” in Proceedings of the Eleventh ACM SIGPLAN Symposium on Principles and Practice of Parallel Programming, ser. PPoPP ’06, 2006, pp. 119–128. [23] G. Bavota, B. D. Carluccio, A. D. Lucia, M. D. Penta, R. Oliveto, and O. Strollo, “When does a refactoring induce bugs? An empirical study,” in Proceedings of the IEEE International Working Conference on Source Code Analysis and Manipulation, ser. SCAM ’12, 2012, pp. 104–113. [24] L. Berardinelli, V. Cortellessa, and A. D. Marco, “Performance modeling and analysis of context-aware mobile software systems,” in Proceedings of the International Conference on Fundamental Approaches to Software Engineering, ser. FASE 10, 2010, pp. 353–367. [25] R. P. L. Buse and W. Weimer, “Synthesizing API usage examples,” in Proceedings of the 34th International Conference on Software Engineering, ser. ICSE ’12, 2012, pp. 782–792. 11 [46] M. Vakilian, D. Dig, R. Bocchino, J. Overbey, V. Adve, and R. Johnson, “Inferring method effect summaries for nested heap regions,” in Proceedings of the IEEE/ACM International Conference on Automated Software Engineering, ser. ASE ’09, 2009, pp. 421–432. [47] J. Wloka, M. Sridharan, and F. Tip, “Refactoring for reentrancy,” in Proceedings of the ACM SIGSOFT Symposium on The Foundations of Software Engineering, ser. FSE ’09, 2009, pp. 173–182. [48] D. Yan, S. Yang, and A. Rountev, “Systematic testing for resource leaks in Android applications,” in Proceedings of the IEEE 24th International Symposium on Software Reliability Engineering, ser. ISSRE 13, 2013, pp. 411–420. [49] S. Yang, D. Yan, and A. Rountev, “Testing for poor responsiveness in Android applications,” in Proceedings of the International Workshop on the Engineering of Mobile-Enabled Systems, ser. MOBS ’13, 2013, pp. 1–6. [50] J. Zhu, J. Hoeflinger, and D. Padua, “Compiling for a hybrid programming model using the lmad representation,” in Proceedings of the 14th International Conference on Languages and Compilers for Parallel Computing, ser. LCPC ’01, 2003, pp. 321–335. 12