4848import java .util .concurrent .ConcurrentLinkedQueue ;
4949import java .util .concurrent .ExecutorService ;
5050import java .util .concurrent .Executors ;
51+ import java .util .concurrent .atomic .AtomicReference ;
5152
5253/**
5354 * Created by fhuya on 11/4/14.
@@ -99,7 +100,7 @@ public void binderDied() {
99100 private DroneObserver droneObserver ;
100101 private DroneApiListener apiListener ;
101102
102- private IDroneApi droneApi ;
103+ private final AtomicReference < IDroneApi > droneApiRef = new AtomicReference <>( null ) ;
103104 private ConnectionParameter connectionParameter ;
104105 private ExecutorService asyncScheduler ;
105106
@@ -132,34 +133,39 @@ Context getContext(){
132133 return this .context ;
133134 }
134135
135- void start () {
136+ synchronized void start () {
136137 if (!serviceMgr .isTowerConnected ())
137138 throw new IllegalStateException ("Service manager must be connected." );
138139
139- if (isStarted ())
140+ IDroneApi droneApi = droneApiRef .get ();
141+ if (isStarted (droneApi ))
140142 return ;
141143
142144 try {
143- this . droneApi = serviceMgr .get3drServices ().registerDroneApi (this .apiListener , serviceMgr .getApplicationId ());
144- this . droneApi .asBinder ().linkToDeath (binderDeathRecipient , 0 );
145+ droneApi = serviceMgr .get3drServices ().registerDroneApi (this .apiListener , serviceMgr .getApplicationId ());
146+ droneApi .asBinder ().linkToDeath (binderDeathRecipient , 0 );
145147 } catch (RemoteException e ) {
146148 throw new IllegalStateException ("Unable to retrieve a valid drone handle." );
147149 }
148150
149151 if (asyncScheduler == null || asyncScheduler .isShutdown ())
150152 asyncScheduler = Executors .newFixedThreadPool (1 );
151153
152- addAttributesObserver (this .droneObserver );
154+ addAttributesObserver (droneApi , this .droneObserver );
153155 resetFlightTimer ();
156+
157+ droneApiRef .set (droneApi );
154158 }
155159
156- void destroy () {
157- removeAttributesObserver (this .droneObserver );
160+ synchronized void destroy () {
161+ IDroneApi droneApi = droneApiRef .get ();
162+
163+ removeAttributesObserver (droneApi , this .droneObserver );
158164
159165 try {
160- if (isStarted ()) {
161- this . droneApi .asBinder ().unlinkToDeath (binderDeathRecipient , 0 );
162- serviceMgr .get3drServices ().releaseDroneApi (this . droneApi );
166+ if (isStarted (droneApi )) {
167+ droneApi .asBinder ().unlinkToDeath (binderDeathRecipient , 0 );
168+ serviceMgr .get3drServices ().releaseDroneApi (droneApi );
163169 }
164170 } catch (RemoteException | NoSuchElementException e ) {
165171 Log .e (TAG , e .getMessage (), e );
@@ -170,7 +176,7 @@ void destroy() {
170176 asyncScheduler = null ;
171177 }
172178
173- droneListeners . clear ( );
179+ droneApiRef . set ( null );
174180 }
175181
176182 private void checkForGroundCollision () {
@@ -193,6 +199,7 @@ private void checkForGroundCollision() {
193199 }
194200
195201 private void handleRemoteException (RemoteException e ) {
202+ final IDroneApi droneApi = droneApiRef .get ();
196203 if (droneApi != null && !droneApi .asBinder ().pingBinder ()) {
197204 final String errorMsg = e .getMessage ();
198205 Log .e (TAG , errorMsg , e );
@@ -245,7 +252,8 @@ public long getFlightTime() {
245252 }
246253
247254 public <T extends Parcelable > T getAttribute (String type ) {
248- if (!isStarted () || type == null )
255+ final IDroneApi droneApi = droneApiRef .get ();
256+ if (!isStarted (droneApi ) || type == null )
249257 return this .getAttributeDefaultValue (type );
250258
251259 T attribute = null ;
@@ -273,7 +281,8 @@ public <T extends Parcelable> void getAttributeAsync(final String attributeType,
273281 if (callback == null )
274282 throw new IllegalArgumentException ("Callback must be non-null." );
275283
276- if (!isStarted ()) {
284+ final IDroneApi droneApi = droneApiRef .get ();
285+ if (!isStarted (droneApi )) {
277286 handler .post (new Runnable () {
278287 @ Override
279288 public void run () {
@@ -414,7 +423,8 @@ public boolean performActionOnDroneThread(Action action, AbstractCommandListener
414423 }
415424
416425 public boolean performActionOnHandler (Action action , final Handler handler , final AbstractCommandListener listener ) {
417- if (isStarted ()) {
426+ final IDroneApi droneApi = droneApiRef .get ();
427+ if (isStarted (droneApi )) {
418428 try {
419429 droneApi .executeAction (action , wrapListener (handler , listener ));
420430 return true ;
@@ -435,7 +445,8 @@ public boolean performAsyncActionOnDroneThread(Action action, AbstractCommandLis
435445 }
436446
437447 public boolean performAsyncActionOnHandler (Action action , Handler handler , AbstractCommandListener listener ) {
438- if (isStarted ()) {
448+ final IDroneApi droneApi = droneApiRef .get ();
449+ if (isStarted (droneApi )) {
439450 try {
440451 droneApi .executeAsyncAction (action , wrapListener (handler , listener ));
441452 return true ;
@@ -447,13 +458,18 @@ public boolean performAsyncActionOnHandler(Action action, Handler handler, Abstr
447458 return false ;
448459 }
449460
450- public boolean isStarted () {
461+ private boolean isStarted (IDroneApi droneApi ) {
451462 return droneApi != null && droneApi .asBinder ().pingBinder ();
452463 }
453464
465+ public boolean isStarted (){
466+ return isStarted (droneApiRef .get ());
467+ }
468+
454469 public boolean isConnected () {
470+ final IDroneApi droneApi = droneApiRef .get ();
455471 State droneState = getAttribute (AttributeType .STATE );
456- return isStarted () && droneState .isConnected ();
472+ return isStarted (droneApi ) && droneState .isConnected ();
457473 }
458474
459475 public ConnectionParameter getConnectionParameter () {
@@ -492,18 +508,19 @@ public void registerDroneListener(DroneListener listener) {
492508 droneListeners .add (listener );
493509 }
494510
495- private void addAttributesObserver (IObserver observer ) {
496- if (isStarted ()) {
511+ private void addAttributesObserver (IDroneApi droneApi , IObserver observer ) {
512+ if (isStarted (droneApi )) {
497513 try {
498- this . droneApi .addAttributesObserver (observer );
514+ droneApi .addAttributesObserver (observer );
499515 } catch (RemoteException e ) {
500516 handleRemoteException (e );
501517 }
502518 }
503519 }
504520
505521 public void addMavlinkObserver (MavlinkObserver observer ) {
506- if (isStarted ()) {
522+ final IDroneApi droneApi = droneApiRef .get ();
523+ if (isStarted (droneApi )) {
507524 try {
508525 droneApi .addMavlinkObserver (observer );
509526 } catch (RemoteException e ) {
@@ -513,7 +530,8 @@ public void addMavlinkObserver(MavlinkObserver observer) {
513530 }
514531
515532 public void removeMavlinkObserver (MavlinkObserver observer ) {
516- if (isStarted ()) {
533+ final IDroneApi droneApi = droneApiRef .get ();
534+ if (isStarted (droneApi )) {
517535 try {
518536 droneApi .removeMavlinkObserver (observer );
519537 } catch (RemoteException e ) {
@@ -529,10 +547,10 @@ public void unregisterDroneListener(DroneListener listener) {
529547 droneListeners .remove (listener );
530548 }
531549
532- private void removeAttributesObserver (IObserver observer ) {
533- if (isStarted ()) {
550+ private void removeAttributesObserver (IDroneApi droneApi , IObserver observer ) {
551+ if (isStarted (droneApi )) {
534552 try {
535- this . droneApi .removeAttributesObserver (observer );
553+ droneApi .removeAttributesObserver (observer );
536554 } catch (RemoteException e ) {
537555 handleRemoteException (e );
538556 }
0 commit comments