2021/2/16 GRIS Welcome to the Research Alumni Portal, Diyu Wu!

You will be able to download the finalised version of all thesis submissions that were processed in GRIS here.

Please ensure to include the completed declaration (from the Declarations tab), your completed Inclusion of Publications Statement (from the Inclusion of Publications Statement tab) in the final version of your thesis that you submit to the Library.

Information on how to submit the final copies of your thesis to the Library is available in the completion email sent to you by the GRS.

Thesis submission for the degree of Doctor of Philosophy

Thesis Title and Abstract Declarations Inclusion of Publications Statement

Corrected Thesis and Responses

Thesis Title

Detecting Event-Based Races in Mobile Applications

Thesis Abstract

Modern mobile platforms have formed their distinct hybrid concurrency system containing both traditional multi-threading and asynchronous event dispatching to support a diverse range of applications. However, this system introduces prevalent concurrency bugs, causing misbehaviour of mobile apps. It is challenging to detect concurrency bugs in mobile apps. Static analysis is prone to a high false positive rate due to the complexity of the hybrid concurrency system, while dynamic analysis suffers from the problem and the existence of conditional statements in programs creates obstacles to dynamically reaching the target statements. This thesis presents two new techniques for detecting event-based races in Android apps, where Android is the dominant mobile platform and has been plagued by event-based races.

First, a novel static analysis tool, called Sard is introduced for detecting event-based races causing use-after-free violations in Android apps. This tool systematically models Android’s concurrency mechanism and applies a novel flow- and context-sensitive static happens-before analysis to reason the interleavings relations between different events and threads. Compared to the prior state-of-the-art tool, Sard achieves better precision (by reporting less false positives and false negatives) and better efficiency.

Second, we propose Sieve, which combines both static and dynamic analysis to detect event- based races in Android apps. Sieve first applies static analysis to find all suspicious races, and then attempts to expose these races dynamically by leveraging a new selective branch instrumentation. For the conditionals potentially affecting a suspicious race, Sieve fixes the true/false outcomes of some of these conditionals based on a systematic branch analysis. By instrumenting certain branches selectively this way, Sieve can not only expose event-based races more effectively than the prior state-of-the-art techniques, but also substantially reduce the negative ramifications of instrumentation. https://www.gris.unsw.edu.au/alumni/ 1/2 2021/2/16 GRIS This thesis presents the methodologies and implementations of both proposed tools and evaluates them using real-world Android apps. The experimental results demonstrate that both Sard and Sieve have met their design goals and bring inspiration on how to perform program analysis on detecting event-based races in event-driven mobile platforms.

https://www.gris.unsw.edu.au/alumni/ 2/2 2021/2/16 GRIS Welcome to the Research Alumni Portal, Diyu Wu!

You will be able to download the finalised version of all thesis submissions that were processed in GRIS here.

Please ensure to include the completed declaration (from the Declarations tab), your completed Inclusion of Publications Statement (from the Inclusion of Publications Statement tab) in the final version of your thesis that you submit to the Library.

Information on how to submit the final copies of your thesis to the Library is available in the completion email sent to you by the GRS.

Thesis submission for the degree of Doctor of Philosophy

Thesis Title and Abstract Declarations Inclusion of Publications Statement

Corrected Thesis and Responses

ORIGINALITY STATEMENT

I hereby declare that this submission is my own work and to the best of my knowledge it contains no materials previously published or written by another person, or substantial proportions of material which have been accepted for the award of any other degree or diploma at UNSW or any other educational institution, except where due acknowledgement is made in the thesis. Any contribution made to the research by others, with whom I have worked at UNSW or elsewhere, is explicitly acknowledged in the thesis. I also declare that the intellectual content of this thesis is the product of my own work, except to the extent that assistance from others in the project's design and conception or in style, presentation and linguistic expression is acknowledged.

COPYRIGHT STATEMENT

I hereby grant the University of New South Wales or its agents a non-exclusive licence to archive and to make available (including to members of the public) my thesis or dissertation in whole or part in the University libraries in all forms of media, now or here after known. I acknowledge that I retain all intellectual property rights which subsist in my thesis or dissertation, such as copyright and patent rights, subject to applicable law. I also retain the right to use all or part of my thesis or dissertation in future works (such as articles or books).

For any substantial portions of copyright material used in this thesis, written permission for use has been obtained, or the copyright material is removed from the final public version of the thesis.

AUTHENTICITY STATEMENT

I certify that the Library deposit digital copy is a direct equivalent of the final officially approved version of my thesis.

https://www.gris.unsw.edu.au/alumni/ 1/2 2021/2/16 GRIS

https://www.gris.unsw.edu.au/alumni/ 2/2 2021/2/16 GRIS Welcome to the Research Alumni Portal, Diyu Wu!

You will be able to download the finalised version of all thesis submissions that were processed in GRIS here.

Please ensure to include the completed declaration (from the Declarations tab), your completed Inclusion of Publications Statement (from the Inclusion of Publications Statement tab) in the final version of your thesis that you submit to the Library.

Information on how to submit the final copies of your thesis to the Library is available in the completion email sent to you by the GRS.

Thesis submission for the degree of Doctor of Philosophy

Thesis Title and Abstract Declarations Inclusion of Publications Statement

Corrected Thesis and Responses

UNSW is supportive of candidates publishing their research results during their candidature as detailed in the UNSW Thesis Examination Procedure.

Publications can be used in the candidate's thesis in lieu of a Chapter provided:

The candidate contributed greater than 50% of the content in the publication and are the "primary author", i.e. they were responsible primarily for the planning, and preparation of the work for publication. The candidate has obtained approval to include the publication in their thesis in lieu of a Chapter from their Supervisor and Postgraduate Coordinator. The publication is not subject to any obligations or contractual agreements with a third party that would constrain its inclusion in the thesis.

The candidate has declared that their thesis has publications - either published or submitted for publication - incorporated into it in lieu of a Chapter/s. Details of these publications are provided below..

Publication Details #1

Full Title: Precise Static Happens-Before Analysis for Detecting UAF Order Violations in Android

Authors: Diyu Wu, Jie Liu, Yulei Sui, Shiping Chen and Jingling Xue

Journal or Book Name: 12th IEEE International Conference on Software Testing, Verification and Validation (ICST'19)

Volume/Page Numbers: 276-287

Date 22/04/2019 Accepted/Published:

Status: published https://www.gris.unsw.edu.au/alumni/ 1/2 2021/2/16 GRIS

The Candidate's The candidate Diyu Wu contributed greater than 70% of the Contribution to the Work: content in the publication and is the primary author of this publication.

Location of the work in Chapter 3 the thesis and/or how the work is incorporated in the thesis:

Publication Details #2

Full Title: Exposing Android Event-Based Races by Selective Branch Instrumentation

Authors: Diyu Wu, Dongjie He, Shiping Chen and Jingling Xue

Journal or Book Name: 31st IEEE International Symposium on Software Reliability Engineering (ISSRE'20)

Volume/Page Numbers:

Date Accepted/Published:

Status: accepted

The Candidate's The candidate Diyu Wu contributed greater than 70% of the Contribution to the Work: content in the publication and is the primary author of this publication.

Location of the work in Chapter 4 the thesis and/or how the work is incorporated in the thesis:

Candidate's Declaration

I confirm that where I have used a publication in lieu of a chapter, the listed publication(s) above meet(s) the requirements to be included in the thesis. I also declare that I have complied with the Thesis Examination Procedure.

https://www.gris.unsw.edu.au/alumni/ 2/2

Android Apps

Dialer Email Calendar Camera …

Java API Framework Managers Content Provider Activity Location Package Notification

View System Resource Telephony Window

Native /C++ Libraries Android Runtime Webkit OpenMAX AL Libc Android Runtime (ART)

Media Framework OpenGL ES … Core Libraries

Hardware Abstraction Layer (HAL) Audio Bluetooth Sensors Camera …

Linux Kernel Drivers Audio Binder (IPC) Display Keypad Bluetooth Shared Camera USB WIFI … Memory

Power Management

External Events Looper thread

Looper Message Queue enqueue enqueue message Message message

Message

… Internal Events Event handler.post(runnable); Message Handler handler.sendMessage(msg); Method ...

1. public class PortForwardListActivity extends Activity{ 2. protected TerminalBridge hostBridge = null; 3. protected Handler updateHandler = new Handler();

4. private ServiceConnection connection = new ServiceConnection(){ 5. public void onServiceConnected(ComponentName className, IBinder service){ 6. PortForwardListActivity.this.hostBridge = new TerminalBridge(); 7. } 8. public void onServiceDisconnected(ComponentName className){ 9. PortForwardListActivity. this.hostBridge = null; 10. } 11. }; event-based race 12. public void onStart(){ 13. bindService(new Intent(this, TerminalManager.class), this.connection, 1); 14. }

15. public void onClick(View arg0){ 16. if(hostBridge == null) return; 17. updateHandler.post(new Runnable(){ 18. public void run() { 19. PortForwardListActivity.this.hostBridge.enablePortForward(); 20. } 21. }); 22. }}

L1:p = null L2:.. = p.use() L1 e1 L2

e2 e1 e2

p.use() p = null

l1 class MyActivity extends Activity{ l2 Field p = new Field(); false alarm HB relations detected by both tools onCreate() a.run() l3 Runnable a = new Runnable(){ reported by l4 public void run(){p.use();}}; nAdroid onCreate() ≺ a . run() ctx: empty ctx: [l16] l5 Runnable c = new Runnable(){ onCreate() ≺ b . run() t(thread): UI t(thread): UI l6 public void run(){p=null;}}; onCreate c run l7 Runnable b = new Runnable(){ () ≺ . () b.run() c.run() l8 public void run(){ HB relations missed by nAdroid ctx: [l17] ctx: [l17, l13] l9 HandlerThread child = but detected by SARD t(thread): UI t(thread): child l10 new HandlerThread(); l11 child.start(); a . run() ≺ b . run() Event-posting relation detected: l l12 Handler hb=new Handler(child.getLooper()); a . run() ≺ c . run() 16 ⟨onCreate(), []⟩@UI ⟨a . run(), [l16]⟩@UI l13 hb.post(c);...}}; A false HB relation generated l17 l14 public void onCreate(){ by nAdroid ⟨onCreate(), []⟩@UI ⟨b . run(), [l17]⟩@UI l l15 Handler handler = new Handler(); ⟨b . run(), [l ]⟩@UI 13 ⟨c . run(), [l , l ]⟩@child l16 handler.post(a); b . run() ≺ c . run() 17 17 13 l17 handler.post(b);}} (c) Abstract event modeling of SARD (a) Example code (b) HB relations l16 1 = ⟨onCreate(), []⟩@UI ⟨a . run(), [l16]⟩@UI onCreate() HB relaiton onCreate() events on same thread l false HB by nAdroid 17 2 = ⟨onCreate(), []⟩@UI ⟨b . run(), [l17]⟩@UI events on same thread missed HB by nAdroid 1 2 l13

3 = ⟨b . run(), [l17]⟩@UI ⟨c . run(), [l17, l13]⟩@child

a.run() b.run() a.run() 4 b.run() events on different threads X 6 4 = 1 + 2 + l dom l 5 16 17 3 5 = 3 + 4 c.run() c.run() 6 = 2 + 3

(d) HB relations before (e) HB relations after (f) Process of building HB relations by SARD being analyzed by SARD being analyzed by SARD

s e ,c @t e ,c @t ! x x" x −→ ! y y" y x cx tx y cy ty s s s! sdoms! s s!

onCreate() a.run() onCreate() b.run() onCreate() c.run() a.run() ≺ ≺ ≺ ≺ b.run() a.run() c.run() a.run() b.run() a.run() ≺ ≺ ≺ c.run() b.run() c.run() ≺

l17,l13 l17 l13

l9 l10

l12 l onCreate(), [] @UI 16 a.run(), [l ] @UI ! " −→ ! 16 "

l16 l onCreate(), [] @UI 17 b.run(), [l ] @UI ! " −→ ! 17 " l b.run(), [l ] @UI 13 c.run(), [l ,l ] @child ! 17 " −→ ! 17 13 "

SARD Static Order Abstract Event Static Happens- Reported Violation Modeling Before Analysis Detection Order Violations

onCreate(), [] a.run(), [l ] onCreate(), [] b.run(), [l ] ! "≺! 16 " ! "≺! 17 "

UI child

l16 dom l17

l4

l6

e, c ! " c C e ∈ e t

UI

e, c @t e ! " t c

s I ∈

Three Event-Creating Abstract Event ⟨e, c⟩@t

handler-based e: a.run() c: [line 6] 1 Runnable a = new Runnable(){ 2 public void run(){...}}; t: child(line 3) 3 HandlerThread child = ⟨a . run(), [l ]⟩@child new HandlerThread(); 6 4 child.start(); 5 Handler handler1 = e: a.run() new Handler(child.getLooper()); c: [line 8] 6 handler1.post(a); t: UI thread(null) 7 Handler handler2 = new Handler(); 8 handler2.post(a); ⟨a . run(), [l8]⟩@UI (a) A handler-based API activity-based e: a.run() 1 Runnable a = new Runnable(){ c: [line 4] 2 public void run(){...}}; t: UI thread(null) 3 public void foo(){ 4 activity.runOnUiThread(a);} ⟨a . run(), [l4]⟩@UI (b) An activity-based API thread-based e: a.run() 1 Runnable a = new Runnable(){ c: [line 5] 2 public void run(){...}}; 3 public void foo(){ t: child(line 4) 4 Thread child = new Thread(a); a run l child 5 child.start();} ⟨ . (), [ 5]⟩@ (c) A thread-based API

m s

e is a callback method e, @UI ! ∅" s : ahandlerbased API call e = getTgt(s) m, c c! = c.append(s) t = getThread(s) ! " e, c! @t ! " s : an activitybased API call e = getTgt(s) m, c c! = c.append(s) ! " e, c! @UI ! " s : an threadbased API call e = getTgt(s) m, c c! = c.append(s) t = getAllocSite(s) ! " e, c! @t ! "

s/I : m! is invoked m, c c! = c.append(s) ∈ ! " m!,c! ! "

e c = ∅

s getTgt(s)

s getThread(s)

e c! t

e, c! @t ! " a.run(), [l ] @child a.run(), [l ] @UI s handler1.post(a) ! 6 " ! 8 " getTgt(s) getThread(s)

s

a.run(), [l ] @UI ! 4 "

s

t getAllocSite(s)

s

a.run(), [l ] @child ! 5 "

s s/I m! s ∈ c m s

c! s c

s ex,cx @tx ey,cy @ty tx = ty ! " −→ ! " e ,c e ,c ! x x"≺! y y" e ,c @t s e ,c @t ! x x" x −→ ! y y" y e ,c @t s! e ,c @t ! x x" x −→ ! z z" z ty = tz sdoms! e ,c e ,c ! y y"≺! z z" e ,c @t s e ,c @t ! x x" x −→ ! y y" y e ,c @t s! e ,c @t ! z z" z −→ ! w w" w ex,cx ez,cz ty = tw ! "≺! " e ,c e ,c ! y y"≺! w w"

ex,ez are callback events e ,c @t s e ,c @t ! x x" x −→ ! y y" y tx = ty ex,cx ez,cz ! "≺! " e ,c e ,c ! y y"≺! z z" e ,c @t s e ,c @t ! y y" y −→ ! z z" z ex,cx ey,cy ! "≺! " e ,c e ,c ! x x"≺! z z"

s e! s e e, c @t e!,c! @t! ! " −→ ! " e t c e!

t! c! s

s ,s s ! use free" use

sfree

e ,c e ,c ! x x"≺! y y" e ,c e ,c e c ! x x" ! y y" x x

ey cy

e ,c t e ,c ! y y" y ! x x" t t = t e ,c e ,c x x y ! x x"≺! y y"

e ,c ! x x" e ,c e ,c e ,c s ! y y" ! z z" ! x x" s! sdoms! s s!

e ,c ! x x" e ,c s! s ! x x" e ,c e ,c ! y y" ! z z" e ,c e ,c e ,c ! y y" ! z z" ! y y" e ,c ! z z"

e ,c e ,c ! y y" ! w w" e ,c e ,c ! x x" ! z z" e ,c e ,c e ,c e ,c ! y y" ! w w" ! y y" ! w w" e ,c e ,c ! x x" ! z z"

e ,c e ,c e ,c ! y y"≺! z z" ! x x" e ,c e ,c e ,c ! x x"≺! z z" ! z z" e ,c e ,c e ,c ! x x" ! x x" ! y y" e ,c e ,c ! y y" ! z z"

e ,c e ,c e ,c e ,c ! x x"≺! y y" ! x x"≺! z z" e ,c e ,c ! z z" ! y y" e ,c e ,c ! x x" ! z z"

suse sfree

Pall s ,s ! use free" suse sfree P

P = suse,sfree Pall suse sfree,sfree suse {! "∈ | (≺ ⇒ }

s s s s use free free ⇒ use

sfree suse sfree suse sfree suse

suse sfree suse sfree

1 public void onCreate(){ 1 public void onCreate(){ 2 if(field != null) 2 field = new Field(); 3 field.use();} 3 field.use();}

(a) (b)

1 public void onCreate(){ 1 public void onCreate(){ 2 field = getField(); 2 field = null; 3 field.use();} 3 field = new Field();}

(c) (d)

1 public void onCreate(){ 1 public void onCreate(){ 2 field = null; 2 field = null; 3 field = getField(); 3 finish();}

(e) (f)

sfree suse

||

ex ey e ,c ! x x" e ,c ! y y"

[CALLBACK RELATION] 18.06%

[INTRA-POST] 20.40%

[INTRA-SAME] 2.98% Remaining Filtered Out 32%(2781) 68%(5881) [INTRA-DIFFERENT] 13.20%

[INTRA-INFER] 22.65%

[COMBO] 22.72%

∩ \ \ \ ∩ \

1 DataSourceManager dataSourceManager; 2 Handler handler; 3 public void onStart(){ 4 dataSourceManager = new DataSourceManager(); 5 HandlerThread ht = new HandlerThread(); 6 ht.start(); 7 handler = new Handler(myThread.getLooper()); 8 handler.post(new Runnable(){ 9 public void run(){ 10 if(dataSourceManager!=null){ 11 dataSourceManager.update();} 12 }});} 13 public void onStop(){ 14 dataSourceManager = null;}

field use path 1. public class MyActivity extends Activity{ 2. MyClass myClass = new MyClass(); 20. public class MyClass{ line 10 onClick() play() line 26 3. Button hello = (Button) findViewById(R.id.hello); 21. Object init = null; 4. Button set = (Button) findViewById(R.id.set); 22. SoundPool sound = new SoundPool(); 5. public void onCreate(){ 1 6. hello.setOnClickListener(new OnClickListener(){ 23. public void play(){ str != null 7. public void onClick(View view) { 24. 3 if(this.init != null){ 25. this.init.foo(); 8. String str = (String) view.getTag(); 2 str.equals("hello") 9. 1 if(str!=null&&str.equals("hello")) 2 26. this.sound.play();} 10. MyActivity.this.myClass.play(); 27. } 11. }}); 3 this.init != null 12. set.setOnClickListener(new OnClickListener(){ 28. public void setInit() { suspicious 13. public void onClick(View arg0) { 29. this.init = new Object(); event-based race 14. MyActivity.this.myClass.setInit(); 30. } field free path 15. }}); 16. } 31. public void shutDown(){ line 18 32. 4 if(this.sound != null) onPause() shutDown() line 33 17. public void onPause(){ 33. this.sound = null; 18. this.myClass.shutDown(); 34. } 4 this.sound != null 19. }} 35. }

(a) Code example of a suspicious event-based race (b) Guarding conditionals for the racy statements

the field use statement unreachable some conditionals unsatisfiable Dynamic Execution

field use tuple Collecting Conditionals Branch Analysis

suspicious Instrumentation races Static Race field free tuple Collecting Conditionals Branch Analysis Results Analysis Tool

some conditionals unsatisfiable the field free statement unreachable

su sf

eu ef

su sf Cu Cf ctx =[I ,I , ,I ] 1 2 ··· n

τ ,τ τ = ! u f " p s ,e ,ctx p u, f s e ! p p p" ∈{ } p p sp ctxp Cp ∈

s ,e ,ctx ! p p p"

sp ep ctxp

ctxp! Cp

τu τf

ctxu ctxf

Cu Cf

τ : s, e, ctx t s ctx ! " ∈{ }∪ t { }⊆W

w t stmt( w) ∈W ∈ M g t t w −→ t t { }⊆W{}⊆W

s, e, ctx ! " s

s W ctx t Mw w w t t W g w t w t −→ W W

W C s, e, ctx ! " C s

s W ctx

t w w t t Mw W g w t w t −→ W C

C

c ∈C c

v c d d ∈ DefStmt(v) v, d v, d ! " D ! "∈D

d : x = l v l

v, d v, d! d! DefStmt(l) ! " D {! "| ∈ } D d! l

pi d : x = pi p Md i I ctx

ai d!

d : x = .f f f

f

s .f

fieldDefStmt() .f

.f x.f = ··· x d!

entries d!

d! c v

e ed! e ⊀ ed!

0 0 / V∪{ } ∈V 0

0 V 2V∪{ } ∈

c v variables(c) ∈C ∈ = v, d d DefStmt(v) D D∪{! "| ∈ } v, d d : x = ll ! "∈D = v, d v, d! d! DefStmt(l) D D\{! "}∪{! "| ∈ } τ : s, e, ctx v, d I ctx I ! "! "∈D ∈ Md p i Md d : x = pi ai = argument(pi,I) = v, d v, d! d! DefStmt(a ) D D\{! "}∪{! "| ∈ i } τ : s, e, ctx v, d d : x = .f ! "! "∈D .f .f s = d! d! fieldDefStmt(.f) ed entries(d!) e ⊀ ed F { | ∈ ! ∈ ! } = v, d v, d! d! D D\{! "}∪{! "| ∈F}

v

v

V v

v

v

v, d d : x = p ! "∈D i pi Vv V⊆ v, d d : x = foo() ! "∈D Vv V⊆ v, d d : x = .f ! "∈D .f Vv V⊆ v, d d : x = T () ! "∈D T () Vv { }⊆ v, d d : x = constant ! "∈D constant Vv { }⊆ τ : s, e, ctx v, d d : x = .f ! "! "∈D .f s 0 Vv { }⊆ v, d d : x = b otherF orm(a) ! "∈D ∈ 0 Vv { }⊆

v .f

s

v v

v

τ : s, e, ctx C ! "

c ! >, = ( ≤ V1 V2 0 satisfy(V1, V2, !)

v1 v2 v1 v2 V1 V2 × ∈ × ! c 0 c

c S

c τ : s, e, ctx ! " e c

c : v constant 0 / Vv ! ∈C ∈ satisfy(Vv, constant , !) { } c { }⊆S

c : vi vj 0 / Vvi 0 / Vvj ! ∈C ∈ ∈ satisfy(Vvi , Vvj , !) c { }⊆S

τ : s, e, ctx cs eo entries(cs) ! " g ∈S u ∈ i stmt( cs ) cs ics ieo = eeo ⊀ e ∈ M −→ −→( ( c { }⊆I

c s ∈S

i g c c i i c s s −→ s u c i −→(

cs i cs

cs

eo cs eo e

eo ⊀ e

I

τu τf

sf su

ef eu

sf su

su

sf su sf

1. public void use(){ Thread 1: 2. synchronized(signal){ 1. public void use(){ 3. if(field!=null){ 2. if(field!=null){ 4. signal.wait(); 3. field.foo(); 5. field.foo();}} 4. } 6. } 5. }

7. public void free(){ Thread 2: 8. synchronized(signal){ 6. public void free(){ 9. field = null; 7. field = null; 10. signal.notify();} 8. } 11.} (a) original code (b) instrumented code

→ →

su sf

sf su

τ : s ,e ,ctx p f,u p ! p p p" ∈{ } Qp

ep

e p Qp

τ τ u f Qu Qf

Qf Qu

||

x x

Uninstrumented Conditionals: 23 - 28.4%

Hidden UI Widgets: 24 - 29.6%

Uninvoked Methods: 16 - 19.8%

Crashes: 7 - 8.6%

Others: 11 - 13.6%

VitoshaDM

1. public void onCreate(){ 2. this.rollMode = false; 3. this.sounds = new SoundPool(); 4. Timer timer = new Timer(); 5. timer.schedule(new TimerTask(){ 6. public void run(){ 7. roll(); 8. }}, 0, 100);}

9. public void roll(){ 10. if(rollMode){ 11. this.sounds.play(); 12. this.rollMode = false;}}

13. public void onClick(){ 14. this.rollMode = true;} 15. public void onDestroy(){ 16. this.sounds = null;}

100 100 100100 100100 100100 100 100100 100 91 80 75 77 77 64 6565 5050 50 5050 50 46 40

2020

17 4 0 0 0 0 0

Ringdroid

1. public void onCreate(){ 2. this.mPlayer = null; 3. this.mIsPlaying = false; 4. load();}

5. public void load(){ ... 6. update(); 7. mPlayer = new SamplePlayer();}

8. public void update(){ 9. if(mIsPlaying) if(true) 10. mPlayer.getCurrentPosition();}

11. public void onClick(){ ... 12. update();}