gt:         if (data != null)
context: package com.fuav.android.api;
  
  import android.content.Context;
  import android.content.Intent;
  import android.os.Bundle;
  import android.os.IBinder;
  import android.os.RemoteException;
  import android.text.TextUtils;
  import android.util.Pair;
  import android.view.Surface;
  
  import com.MAVLink.Messages.MAVLinkMessage;
  import com.MAVLink.ardupilotmega.msg_mag_cal_progress;
  import com.MAVLink.ardupilotmega.msg_mag_cal_report;
  import com.o3dr.services.android.lib.drone.action.CameraActions;
  import com.o3dr.services.android.lib.coordinate.LatLongAlt;
  import com.o3dr.services.android.lib.drone.action.ConnectionActions;
  import com.o3dr.services.android.lib.drone.attribute.AttributeEvent;
  import com.o3dr.services.android.lib.drone.attribute.AttributeEventExtra;
  import com.o3dr.services.android.lib.drone.attribute.AttributeType;
  import com.o3dr.services.android.lib.drone.attribute.error.CommandExecutionError;
  import com.o3dr.services.android.lib.drone.connection.ConnectionParameter;
  import com.o3dr.services.android.lib.drone.connection.ConnectionResult;
  import com.o3dr.services.android.lib.drone.connection.DroneSharePrefs;
  import com.o3dr.services.android.lib.drone.mission.Mission;
  import com.o3dr.services.android.lib.drone.mission.action.MissionActions;
  import com.o3dr.services.android.lib.drone.mission.item.MissionItem;
  import com.o3dr.services.android.lib.drone.mission.item.command.ResetROI;
  import com.o3dr.services.android.lib.drone.mission.item.spatial.RegionOfInterest;
  import com.o3dr.services.android.lib.drone.property.DroneAttribute;
  import com.o3dr.services.android.lib.drone.property.Parameter;
  import com.o3dr.services.android.lib.gcs.event.GCSEvent;
  import com.o3dr.services.android.lib.mavlink.MavlinkMessageWrapper;
  import com.o3dr.services.android.lib.model.IApiListener;
  import com.o3dr.services.android.lib.model.ICommandListener;
  import com.o3dr.services.android.lib.model.IDroneApi;
  import com.o3dr.services.android.lib.model.IMavlinkObserver;
  import com.o3dr.services.android.lib.model.IObserver;
  import com.o3dr.services.android.lib.model.action.Action;
  
  import com.fuav.android.core.drone.DroneInterfaces;
  import com.fuav.android.core.drone.DroneManager;
  import com.fuav.android.core.drone.autopilot.MavLinkDrone;
  import com.fuav.android.core.drone.variables.calibration.AccelCalibration;
  import com.fuav.android.core.drone.variables.calibration.MagnetometerCalibrationImpl;
  import com.fuav.android.exception.ConnectionException;
  import com.fuav.android.utils.CommonApiUtils;
  import com.fuav.android.utils.video.VideoManager;
  
  import java.util.ArrayList;
  import java.util.List;
  import java.util.NoSuchElementException;
  import java.util.concurrent.ConcurrentLinkedQueue;
  
  import timber.log.Timber;
  
  /**
   * Implementation for the IDroneApi interface.
   */
   public final class DroneApi extends IDroneApi.Stub implements DroneInterfaces.OnDroneListener, DroneInterfaces.AttributeEventListener,
          DroneInterfaces.OnParameterManagerListener, MagnetometerCalibrationImpl.OnMagnetometerCalibrationListener, IBinder.DeathRecipient {
  
      //The Reset ROI mission item was introduced in version 2.6.8. Any client library older than this do not support it.
      private final static int RESET_ROI_LIB_VERSION = 206080;
  
      private final Context context;
  
      private final ConcurrentLinkedQueue<IObserver> observersList;
      private final ConcurrentLinkedQueue<IMavlinkObserver> mavlinkObserversList;
      private DroneManager droneMgr;
      private final IApiListener apiListener;
  
      private final String ownerId;
      private final ClientInfo clientInfo;
  
      private final DroidPlannerService service;
  
      private ConnectionParameter connectionParams;
  
      public DroneApi(DroidPlannerService dpService, IApiListener listener, String ownerId) {
  
          this.service = dpService;
          this.context = dpService.getApplicationContext();
  
          this.ownerId = ownerId;
  
          observersList = new ConcurrentLinkedQueue<>();
          mavlinkObserversList = new ConcurrentLinkedQueue<>();
  
          this.apiListener = listener;
          int apiVersionCode = -1;
          int clientVersionCode = -1;
          try {
              this.apiListener.asBinder().linkToDeath(this, 0);
              checkForSelfRelease();
  
              apiVersionCode = apiListener.getApiVersionCode();
              clientVersionCode = apiListener.getClientVersionCode();
          } catch (RemoteException e) {
              Timber.e(e, e.getMessage());
              dpService.releaseDroneApi(this.ownerId);
          }
  
          this.clientInfo = new ClientInfo(this.ownerId, apiVersionCode, clientVersionCode);
      }
  
      void destroy() {
          Timber.d("Destroying drone api instance for %s", this.ownerId);
          this.observersList.clear();
          this.mavlinkObserversList.clear();
  
          try {
              this.apiListener.asBinder().unlinkToDeath(this, 0);
          } catch (NoSuchElementException e) {
              Timber.e(e, e.getMessage());
          }
  
          try {
              this.service.disconnectDroneManager(this.droneMgr, this.clientInfo);
          } catch (ConnectionException e) {
              Timber.e(e, e.getMessage());
          }
      }
  
      public String getOwnerId() {
          return ownerId;
      }
  
      public DroneManager getDroneManager() {
          return this.droneMgr;
      }
  
      private MavLinkDrone getDrone() {
          if (this.droneMgr == null)
              return null;
  
          return this.droneMgr.getDrone();
      }
  
      @Override
      public Bundle getAttribute(String type) throws RemoteException {
          Bundle carrier = new Bundle();
  
          switch (type) {
              case AttributeType.CAMERA:
                  carrier.putParcelable(type, CommonApiUtils.getCameraProxy(getDrone(), service.getCameraDetails()));
                  break;
  
              default:
                  if(droneMgr != null) {
                      DroneAttribute attribute = droneMgr.getAttribute(clientInfo, type);
                      if (attribute != null) {
  
                          //Check if the client supports the ResetROI mission item.
                          // Replace it with a RegionOfInterest with coordinate set to 0 if it doesn't.
                          if(clientInfo.clientVersionCode < RESET_ROI_LIB_VERSION && attribute instanceof Mission){
                              Mission proxyMission = (Mission) attribute;
                              List<MissionItem> missionItems = proxyMission.getMissionItems();
                              int missionItemsCount = missionItems.size();
                              for(int i = 0; i < missionItemsCount; i++){
                                  MissionItem missionItem = missionItems.get(i);
                                  if(missionItem instanceof ResetROI){
                                      missionItems.remove(i);
  
                                      RegionOfInterest replacement = new RegionOfInterest();
                                      replacement.setCoordinate(new LatLongAlt(0, 0, 0));
                                      missionItems.add(i, replacement);
                                  }
                              }
                          }
  
                          carrier.putParcelable(type, attribute);
                      }
                  }
                  break;
          }
          return carrier;
      }
  
      public boolean isConnected() {
          return droneMgr != null && droneMgr.isConnected();
      }
  
      public void connect(ConnectionParameter connParams) {
          try {
              this.connectionParams = connParams;
              this.droneMgr = service.connectDroneManager(connParams, ownerId, this);
          } catch (ConnectionException e) {
              notifyConnectionFailed(new ConnectionResult(0, e.getMessage()));
              disconnect();
          }
      }
  
      public void disconnect() {
          try {
              service.disconnectDroneManager(this.droneMgr, clientInfo);
              this.droneMgr = null;
          } catch (ConnectionException e) {
              notifyConnectionFailed(new ConnectionResult(0, e.getMessage()));
          }
      }
  
      private void checkForSelfRelease() {
          //Check if the apiListener is still connected instead.
          if (!apiListener.asBinder().pingBinder()) {
              Timber.w("Client is not longer available.");
              this.context.startService(new Intent(this.context, DroidPlannerService.class)
                      .setAction(DroidPlannerService.ACTION_RELEASE_API_INSTANCE)
                      .putExtra(DroidPlannerService.EXTRA_API_INSTANCE_APP_ID, this.ownerId));
          }
      }
  
      @Override
      public void addAttributesObserver(IObserver observer) throws RemoteException {
          if (observer != null) {
              Timber.d("Adding attributes observer.");
              observersList.add(observer);
          }
      }
  
      @Override
      public void removeAttributesObserver(IObserver observer) throws RemoteException {
          if (observer != null) {
              Timber.d("Removing attributes observer.");
              observersList.remove(observer);
              checkForSelfRelease();
          }
      }
  
      @Override
      public void addMavlinkObserver(IMavlinkObserver observer) throws RemoteException {
          if (observer != null)
              mavlinkObserversList.add(observer);
      }
  
      @Override
      public void removeMavlinkObserver(IMavlinkObserver observer) throws RemoteException {
          if (observer != null) {
              mavlinkObserversList.remove(observer);
              checkForSelfRelease();
          }
      }
  
      @Override
      public void executeAction(Action action, ICommandListener listener) throws RemoteException {
          if (action == null)
              return;
  
          String type = action.getType();
          if (type == null)
              return;
  
          Bundle data = action.getData();
  