1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-11-30 08:24:11 +01:00

Merge branch 'android-uavo-fix' into next

This commit is contained in:
James Cotton 2012-10-16 14:27:01 -05:00
commit 1c89b24329
5 changed files with 189 additions and 144 deletions

View File

@ -294,6 +294,7 @@ public class OPTelemetryService extends Service {
numRead = inputStream.read(buffer); numRead = inputStream.read(buffer);
} }
} }
private void copyAssets(String JAR_DIR, String JAR_NAME) private void copyAssets(String JAR_DIR, String JAR_NAME)
{ {
File jarsDir = getDir(JAR_DIR, MODE_WORLD_READABLE); File jarsDir = getDir(JAR_DIR, MODE_WORLD_READABLE);
@ -320,6 +321,19 @@ public class OPTelemetryService extends Service {
catch (IOException e) catch (IOException e)
{ {
Log.e(TAG, e.toString(), e); Log.e(TAG, e.toString(), e);
String[] list;
try {
list = assetManager.list("uavos/");
Log.i(TAG, "Listing found uavos");
for(int i = 0; i < list.length; i++) {
Log.i(TAG, "Found: " + list[i]);
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} }
} }
@ -351,6 +365,10 @@ public class OPTelemetryService extends Service {
final String JAR_DIR = "jars"; final String JAR_DIR = "jars";
final String DEX_DIR = "optimized_dex"; final String DEX_DIR = "optimized_dex";
File jarsDir = getDir(JAR_DIR, MODE_WORLD_READABLE);
if (jarsDir.exists())
deleteDirectoryContents(jarsDir);
copyAssets(JAR_DIR, jar); copyAssets(JAR_DIR, jar);
Log.d(TAG, "Starting dex loader"); Log.d(TAG, "Starting dex loader");
@ -360,7 +378,6 @@ public class OPTelemetryService extends Service {
if (dexDir.exists()) if (dexDir.exists())
deleteDirectoryContents(dexDir); deleteDirectoryContents(dexDir);
File jarsDir = getDir(JAR_DIR, MODE_WORLD_READABLE);
String classpath = new File(jarsDir, jar).getAbsolutePath(); String classpath = new File(jarsDir, jar).getAbsolutePath();
DexClassLoader loader = new DexClassLoader(classpath, dexDir.getAbsolutePath(), null, getClassLoader()); DexClassLoader loader = new DexClassLoader(classpath, dexDir.getAbsolutePath(), null, getClassLoader());

View File

@ -8,8 +8,6 @@ import java.util.Observer;
import org.openpilot.uavtalk.Telemetry; import org.openpilot.uavtalk.Telemetry;
import org.openpilot.uavtalk.TelemetryMonitor; import org.openpilot.uavtalk.TelemetryMonitor;
import org.openpilot.uavtalk.UAVObject;
import org.openpilot.uavtalk.UAVObjectField;
import org.openpilot.uavtalk.UAVObjectManager; import org.openpilot.uavtalk.UAVObjectManager;
import org.openpilot.uavtalk.UAVTalk; import org.openpilot.uavtalk.UAVTalk;
import org.openpilot.uavtalk.uavobjects.TelemObjectsInitialize; import org.openpilot.uavtalk.uavobjects.TelemObjectsInitialize;
@ -93,32 +91,6 @@ public abstract class TelemetryTask implements Runnable {
*/ */
abstract boolean attemptConnection(); abstract boolean attemptConnection();
private final Observer firmwareIapUpdated = new Observer() {
@Override
public void update(Observable observable, Object data) {
if (DEBUG) Log.d(TAG, "Received firmware IAP Updated message");
UAVObject obj = objMngr.getObject("FirmwareIAPObj");
UAVObjectField description = obj.getField("Description");
if(description == null || description.getNumElements() < 100) {
telemService.toastMessage("Failed to determine UAVO set");
} else {
final int HASH_SIZE_USED = 8;
String jarName = new String();
for(int i = 0; i < HASH_SIZE_USED; i++)
jarName += Integer.toHexString((int) description.getDouble(i+60));
jarName += ".jar";
if (DEBUG) Log.d(TAG, "Attempting to load: " + jarName);
if (telemService.loadUavobjects(jarName, objMngr) ) {
telemService.toastMessage("Loaded appropriate UAVO set");
} else
telemService.toastMessage("Failed to determine UAVO set");
}
obj.removeUpdatedObserver(this);
}
};
/** /**
* Called when a physical channel is opened * Called when a physical channel is opened
* *
@ -133,11 +105,6 @@ public abstract class TelemetryTask implements Runnable {
objMngr = new UAVObjectManager(); objMngr = new UAVObjectManager();
TelemObjectsInitialize.register(objMngr); TelemObjectsInitialize.register(objMngr);
// Register to get an update from FirmwareIAP in order to register
// the appropriate objects
UAVObject obj = objMngr.getObject("FirmwareIAPObj");
obj.addUpdatedObserver(firmwareIapUpdated);
// Create the required telemetry objects attached to this // Create the required telemetry objects attached to this
// data stream // data stream
uavTalk = new UAVTalk(inStream, outStream, objMngr); uavTalk = new UAVTalk(inStream, outStream, objMngr);

View File

@ -202,7 +202,7 @@ public class Telemetry {
/** /**
* Register a new object for periodic updates (if enabled) * Register a new object for periodic updates (if enabled)
*/ */
private synchronized void registerObject(UAVObject obj) { private void registerObject(UAVObject obj) {
// Setup object for periodic updates // Setup object for periodic updates
addObject(obj); addObject(obj);
@ -213,7 +213,9 @@ public class Telemetry {
/** /**
* Add an object in the list used for periodic updates * Add an object in the list used for periodic updates
*/ */
private synchronized void addObject(UAVObject obj) { private void addObject(UAVObject obj) {
synchronized (objList) {
// Check if object type is already in the list // Check if object type is already in the list
ListIterator<ObjectTimeInfo> li = objList.listIterator(); ListIterator<ObjectTimeInfo> li = objList.listIterator();
while (li.hasNext()) { while (li.hasNext()) {
@ -232,6 +234,7 @@ public class Telemetry {
timeInfo.updatePeriodMs = 0; timeInfo.updatePeriodMs = 0;
objList.add(timeInfo); objList.add(timeInfo);
} }
}
/** /**
* Update the object's timers * Update the object's timers
@ -281,7 +284,7 @@ public class Telemetry {
* Connect to all instances of an object depending on the event mask * Connect to all instances of an object depending on the event mask
* specified * specified
*/ */
private synchronized void connectToObjectInstances(UAVObject obj, private void connectToObjectInstances(UAVObject obj,
int eventMask) { int eventMask) {
List<UAVObject> objs = objMngr.getObjectInstances(obj.getObjID()); List<UAVObject> objs = objMngr.getObjectInstances(obj.getObjID());
ListIterator<UAVObject> li = objs.listIterator(); ListIterator<UAVObject> li = objs.listIterator();
@ -312,6 +315,8 @@ public class Telemetry {
* Update an object based on its metadata properties * Update an object based on its metadata properties
*/ */
private void updateObject(UAVObject obj) { private void updateObject(UAVObject obj) {
synchronized(obj) {
// Get metadata // Get metadata
UAVObject.Metadata metadata = obj.getMetadata(); UAVObject.Metadata metadata = obj.getMetadata();
@ -351,6 +356,7 @@ public class Telemetry {
connectToObjectInstances(obj, eventMask); connectToObjectInstances(obj, eventMask);
} }
} }
}
/** /**
* Check is any objects are pending for periodic updates TODO: Clean-up * Check is any objects are pending for periodic updates TODO: Clean-up
@ -448,7 +454,7 @@ public class Telemetry {
registerObject(obj); registerObject(obj);
} }
private synchronized void newInstance(UAVObject obj) { private void newInstance(UAVObject obj) {
registerObject(obj); registerObject(obj);
} }
@ -632,11 +638,7 @@ public class Telemetry {
return; return;
} }
// Store this as the active transaction if (DEBUG) Log.d(TAG, "Process Object transaction for " + newTrans.obj.getName());
transPending = newTransactionPending;
transInfo = newTrans;
if (DEBUG) Log.d(TAG, "Process Object transaction for " + transInfo.obj.getName());
// Remove this one from the list of pending transactions // Remove this one from the list of pending transactions
handler.removeActivatedQueue(objInfo); handler.removeActivatedQueue(objInfo);
@ -644,12 +646,12 @@ public class Telemetry {
try { try {
// 3. Execute transaction by sending the appropriate UAVTalk command // 3. Execute transaction by sending the appropriate UAVTalk command
if (transInfo.objRequest) { if (newTrans.objRequest) {
if (DEBUG) Log.d(TAG, "Sending object request " + transInfo.obj.getName()); if (DEBUG) Log.d(TAG, "Sending object request " + newTrans.obj.getName());
utalk.sendObjectRequest(transInfo.obj, transInfo.allInstances); utalk.sendObjectRequest(newTrans.obj, newTrans.allInstances);
} else { } else {
if (DEBUG) Log.d(TAG, "Sending object " + transInfo.obj.getName()); if (DEBUG) Log.d(TAG, "Sending object " + newTrans.obj.getName());
utalk.sendObject(transInfo.obj, transInfo.acked, transInfo.allInstances); utalk.sendObject(newTrans.obj, newTrans.acked, newTrans.allInstances);
} }
} catch (IOException e) { } catch (IOException e) {
@ -657,10 +659,18 @@ public class Telemetry {
e.printStackTrace(); e.printStackTrace();
} }
// Store this as the active transaction. However in the case
// of transPending && !newTransactionPending we need ot not
// override the previous pending transaction
if (!transPending && newTransactionPending) {
transPending = newTransactionPending;
transInfo = newTrans;
// Post a timeout timer if a response is epxected // Post a timeout timer if a response is epxected
if (transPending)
handler.postDelayed(transactionTimeout, REQ_TIMEOUT_MS); handler.postDelayed(transactionTimeout, REQ_TIMEOUT_MS);
} }
}
} }
} }
} }
@ -744,7 +754,7 @@ public class Telemetry {
//Send signal //Send signal
obj.transactionCompleted(result); obj.transactionCompleted(result);
} else { } else {
if (ERROR) Log.e(TAG, "Error: received a transaction completed when did not expect it."); if (ERROR) Log.e(TAG, "Error: received a transaction completed when did not expect it. " + obj.getName());
transPending = false; transPending = false;
} }
} }

View File

@ -54,9 +54,12 @@ public class TelemetryMonitor extends Observable {
private final UAVObjectManager objMngr; private final UAVObjectManager objMngr;
private final Telemetry tel; private final Telemetry tel;
private boolean objectsRegistered;
// private UAVObject objPending; // private UAVObject objPending;
private UAVObject gcsStatsObj; private UAVObject gcsStatsObj;
private UAVObject flightStatsObj; private UAVObject flightStatsObj;
private final UAVObject firmwareIapObj;
private Timer periodicTask; private Timer periodicTask;
private int currentPeriod; private int currentPeriod;
private long lastUpdateTime; private long lastUpdateTime;
@ -74,7 +77,8 @@ public class TelemetryMonitor extends Observable {
return objects_updated; return objects_updated;
}; };
public TelemetryMonitor(UAVObjectManager objMngr, Telemetry tel, OPTelemetryService s) { public TelemetryMonitor(UAVObjectManager objMngr, Telemetry tel,
OPTelemetryService s) {
this(objMngr, tel); this(objMngr, tel);
telemService = s; telemService = s;
} }
@ -85,9 +89,15 @@ public class TelemetryMonitor extends Observable {
// this.objPending = null; // this.objPending = null;
queue = new ArrayList<UAVObject>(); queue = new ArrayList<UAVObject>();
objectsRegistered = false;
// Get stats objects // Get stats objects
gcsStatsObj = objMngr.getObject("GCSTelemetryStats"); gcsStatsObj = objMngr.getObject("GCSTelemetryStats");
flightStatsObj = objMngr.getObject("FlightTelemetryStats"); flightStatsObj = objMngr.getObject("FlightTelemetryStats");
firmwareIapObj = objMngr.getObject("FirmwareIAPObj");
// The first update of the firmwareIapObj will trigger registering the objects
firmwareIapObj.addUpdatedObserver(firmwareIapUpdated);
flightStatsObj.addUpdatedObserver(new Observer() { flightStatsObj.addUpdatedObserver(new Observer() {
@Override @Override
@ -360,8 +370,13 @@ public class TelemetryMonitor extends Observable {
setPeriod(STATS_UPDATE_PERIOD_MS); setPeriod(STATS_UPDATE_PERIOD_MS);
connected = true; connected = true;
objects_updated = false; objects_updated = false;
if (objectsRegistered)
startRetrievingObjects(); startRetrievingObjects();
if (HANDSHAKE_IS_CONNECTED) setChanged(); // Enabling this line makes the opConnected signal occur whenever we get a handshake else
firmwareIapObj.updateRequested();
if (HANDSHAKE_IS_CONNECTED)
setChanged(); // Enabling this line makes the opConnected signal
// occur whenever we get a handshake
} }
if (gcsDisconnected && gcsStatusChanged) { if (gcsDisconnected && gcsStatusChanged) {
if (DEBUG) if (DEBUG)
@ -405,4 +420,37 @@ public class TelemetryMonitor extends Observable {
periodicTask = null; periodicTask = null;
} }
private final Observer firmwareIapUpdated = new Observer() {
@Override
public void update(Observable observable, Object data) {
if (DEBUG) Log.d(TAG, "Received firmware IAP Updated message");
UAVObjectField description = firmwareIapObj.getField("Description");
if (description == null || description.getNumElements() < 100) {
telemService.toastMessage("Failed to determine UAVO set");
} else {
final int HASH_SIZE_USED = 8;
String jarName = new String();
for (int i = 0; i < HASH_SIZE_USED; i++) {
jarName += String.format("%02x", (int) description.getDouble(i + 60));
}
jarName += ".jar";
if (DEBUG) Log.d(TAG, "Attempting to load: " + jarName);
if (telemService.loadUavobjects(jarName, objMngr)) {
telemService.toastMessage("Loaded appropriate UAVO set");
objectsRegistered = true;
try {
startRetrievingObjects();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else
telemService.toastMessage("Failed to load UAVO set: " + jarName);
}
firmwareIapObj.removeUpdatedObserver(this);
}
};
} }

View File

@ -269,7 +269,8 @@ public class UAVTalk {
* it wants to give up on one (after a timeout) then it can cancel it * it wants to give up on one (after a timeout) then it can cancel it
* @return True if that object was pending, False otherwise * @return True if that object was pending, False otherwise
*/ */
public synchronized boolean cancelPendingTransaction(UAVObject obj) { public boolean cancelPendingTransaction(UAVObject obj) {
synchronized (respObj) {
if(respObj != null && respObj.getObjID() == obj.getObjID()) { if(respObj != null && respObj.getObjID() == obj.getObjID()) {
if(transactionListener != null) { if(transactionListener != null) {
Log.d(TAG,"Canceling transaction: " + respObj.getName()); Log.d(TAG,"Canceling transaction: " + respObj.getName());
@ -280,6 +281,7 @@ public class UAVTalk {
} else } else
return false; return false;
} }
}
/** /**
* Cancel a pending transaction. If there is a pending transaction and * Cancel a pending transaction. If there is a pending transaction and
@ -296,8 +298,8 @@ public class UAVTalk {
/** /**
* This is the code that sets up a new UAVTalk packet that expects a response. * This is the code that sets up a new UAVTalk packet that expects a response.
*/ */
private synchronized void setupTransaction(UAVObject obj, boolean allInstances, int type) { private void setupTransaction(UAVObject obj, boolean allInstances, int type) {
synchronized (this) {
// Only cancel if it is for a different object // Only cancel if it is for a different object
if(respObj != null && respObj.getObjID() != obj.getObjID()) if(respObj != null && respObj.getObjID() != obj.getObjID())
cancelPendingTransaction(obj); cancelPendingTransaction(obj);
@ -306,6 +308,7 @@ public class UAVTalk {
respAllInstances = allInstances; respAllInstances = allInstances;
respType = type; respType = type;
} }
}
/** /**
* Execute the requested transaction on an object. \param[in] obj Object * Execute the requested transaction on an object. \param[in] obj Object
@ -315,7 +318,7 @@ public class UAVTalk {
* Success (true), Failure (false) * Success (true), Failure (false)
* @throws IOException * @throws IOException
*/ */
private synchronized boolean objectTransaction(UAVObject obj, int type, boolean allInstances) throws IOException { private boolean objectTransaction(UAVObject obj, int type, boolean allInstances) throws IOException {
if (type == TYPE_OBJ_ACK || type == TYPE_OBJ_REQ || type == TYPE_OBJ) { if (type == TYPE_OBJ_ACK || type == TYPE_OBJ_REQ || type == TYPE_OBJ) {
return transmitObject(obj, type, allInstances); return transmitObject(obj, type, allInstances);
} else { } else {
@ -415,7 +418,7 @@ public class UAVTalk {
{ {
UAVObject rxObj = objMngr.getObject(rxObjId); UAVObject rxObj = objMngr.getObject(rxObjId);
if (rxObj == null) { if (rxObj == null) {
if (DEBUG) Log.d(TAG, "Unknown ID: " + rxObjId); if (WARN) Log.w(TAG, "Unknown ID: " + rxObjId);
stats.rxErrors++; stats.rxErrors++;
rxState = RxStateType.STATE_SYNC; rxState = RxStateType.STATE_SYNC;
break; break;
@ -429,17 +432,7 @@ public class UAVTalk {
// Check length and determine next state // Check length and determine next state
if (rxLength >= MAX_PAYLOAD_LENGTH) { if (rxLength >= MAX_PAYLOAD_LENGTH) {
stats.rxErrors++; if (WARN) Log.w(TAG, "Greater than max payload length");
rxState = RxStateType.STATE_SYNC;
break;
}
// Check the lengths match
if ((rxPacketLength + rxLength) != packetSize) { // packet error
// -
// mismatched
// packet
// size
stats.rxErrors++; stats.rxErrors++;
rxState = RxStateType.STATE_SYNC; rxState = RxStateType.STATE_SYNC;
break; break;
@ -503,7 +496,7 @@ public class UAVTalk {
rxCSPacket = rxbyte; rxCSPacket = rxbyte;
if (rxCS != rxCSPacket) { // packet error - faulty CRC if (rxCS != rxCSPacket) { // packet error - faulty CRC
if (DEBUG) Log.d(TAG,"Bad crc"); if (WARN) Log.w(TAG,"Bad crc");
stats.rxErrors++; stats.rxErrors++;
rxState = RxStateType.STATE_SYNC; rxState = RxStateType.STATE_SYNC;
break; break;
@ -512,7 +505,7 @@ public class UAVTalk {
if (rxPacketLength != (packetSize + 1)) { // packet error - if (rxPacketLength != (packetSize + 1)) { // packet error -
// mismatched packet // mismatched packet
// size // size
if (DEBUG) Log.d(TAG,"Bad size"); if (WARN) Log.w(TAG,"Bad size");
stats.rxErrors++; stats.rxErrors++;
rxState = RxStateType.STATE_SYNC; rxState = RxStateType.STATE_SYNC;
break; break;
@ -529,6 +522,7 @@ public class UAVTalk {
break; break;
default: default:
if (WARN) Log.w(TAG, "Bad state");
rxState = RxStateType.STATE_SYNC; rxState = RxStateType.STATE_SYNC;
stats.rxErrors++; stats.rxErrors++;
} }
@ -701,21 +695,30 @@ public class UAVTalk {
* Called when an object is received to check if this completes * Called when an object is received to check if this completes
* a UAVTalk transaction * a UAVTalk transaction
*/ */
private synchronized void updateObjReq(UAVObject obj) { private void updateObjReq(UAVObject obj) {
// Check if this is not a possible candidate // Check if this is not a possible candidate
Assert.assertNotNull(obj); Assert.assertNotNull(obj);
boolean succeeded = false;
// The lock on UAVTalk must be release before the transaction succeeded signal is sent
// because otherwise if a transaction timeout occurs at the same time we can get a
// deadlock:
// 1. processInputStream -> updateObjReq (locks uavtalk) -> tranactionCompleted (locks transInfo)
// 2. transactionTimeout (locks transInfo) -> sendObjectRequest -> É -> setupTransaction (locks uavtalk)
synchronized(this) {
if(respObj != null && respType == TYPE_OBJ_REQ && respObj.getObjID() == obj.getObjID() && if(respObj != null && respType == TYPE_OBJ_REQ && respObj.getObjID() == obj.getObjID() &&
((respObj.getInstID() == obj.getInstID() || !respAllInstances))) { ((respObj.getInstID() == obj.getInstID() || !respAllInstances))) {
// Indicate complete // Indicate complete
respObj = null; respObj = null;
succeeded = true;
// Notify listener }
if (transactionListener != null)
transactionListener.TransactionSucceeded(obj);
} }
// Notify listener
if (succeeded && transactionListener != null)
transactionListener.TransactionSucceeded(obj);
} }
/** /**