merge heads

This commit is contained in:
Jimmy Shih
2012-02-06 10:12:13 -08:00
4 changed files with 100 additions and 55 deletions
@@ -73,18 +73,18 @@ public class SensorStateActivity extends Activity {
runOnUiThread(stateUpdater); runOnUiThread(stateUpdater);
} }
}; };
/** /**
* A temporary sensor manager, when none is available. * A temporary sensor manager, when none is available.
*/ */
private SensorManager tempSensorManager = null; private SensorManager tempSensorManager = null;
/** /**
* A state flag set to true when the activity is active/visible, * A state flag set to true when the activity is active/visible,
* i.e. after resume, and before pause * i.e. after resume, and before pause
* *
* Used to avoid updating after the pause event, because sometimes an update * Used to avoid updating after the pause event, because sometimes an update
* event occurs even after the timer is cancelled. In this case, * event occurs even after the timer is cancelled. In this case,
* it could cause the {@link #tempSensorManager} to be recreated, after it * it could cause the {@link #tempSensorManager} to be recreated, after it
* is destroyed at the pause event. * is destroyed at the pause event.
@@ -111,7 +111,7 @@ public class SensorStateActivity extends Activity {
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
isVisible = true; isVisible = true;
serviceConnection.bindIfRunning(); serviceConnection.bindIfRunning();
@@ -123,7 +123,7 @@ public class SensorStateActivity extends Activity {
@Override @Override
protected void onPause() { protected void onPause() {
isVisible = false; isVisible = false;
timer.cancel(); timer.cancel();
timer.purge(); timer.purge();
timer = null; timer = null;
@@ -139,9 +139,9 @@ public class SensorStateActivity extends Activity {
private void updateState() { private void updateState() {
Log.d(TAG, "Updating SensorStateActivity"); Log.d(TAG, "Updating SensorStateActivity");
ITrackRecordingService service = serviceConnection.getServiceIfBound(); ITrackRecordingService service = serviceConnection.getServiceIfBound();
// Check if service is available, and recording. // Check if service is available, and recording.
boolean isRecording = false; boolean isRecording = false;
if (service != null) { if (service != null) {
@@ -151,7 +151,7 @@ public class SensorStateActivity extends Activity {
Log.e(TAG, "Unable to determine if service is recording.", e); Log.e(TAG, "Unable to determine if service is recording.", e);
} }
} }
// If either service isn't available, or not recording. // If either service isn't available, or not recording.
if (!isRecording) { if (!isRecording) {
updateFromTempSensorManager(); updateFromTempSensorManager();
@@ -159,19 +159,17 @@ public class SensorStateActivity extends Activity {
updateFromSysSensorManager(); updateFromSysSensorManager();
} }
} }
private void updateFromTempSensorManager() { private void updateFromTempSensorManager() {
// Use variables to hold the sensor state and data set. // Use variables to hold the sensor state and data set.
Sensor.SensorState currentState = null; Sensor.SensorState currentState = null;
Sensor.SensorDataSet currentDataSet = null; Sensor.SensorDataSet currentDataSet = null;
// If no temp sensor manager is present, create one, and start it. // If no temp sensor manager is present, create one, and start it.
if (tempSensorManager == null) { if (tempSensorManager == null) {
tempSensorManager = SensorManagerFactory.getSensorManager(this); tempSensorManager = SensorManagerFactory.getInstance().getSensorManager(this);
if (tempSensorManager != null)
tempSensorManager.onStartTrack();
} }
// If a temp sensor manager is available, use states from temp sensor // If a temp sensor manager is available, use states from temp sensor
// manager. // manager.
if (tempSensorManager != null) { if (tempSensorManager != null) {
@@ -182,15 +180,15 @@ public class SensorStateActivity extends Activity {
// Update the sensor state, and sensor data, using the variables. // Update the sensor state, and sensor data, using the variables.
updateSensorStateAndData(currentState, currentDataSet); updateSensorStateAndData(currentState, currentDataSet);
} }
private void updateFromSysSensorManager() { private void updateFromSysSensorManager() {
// Use variables to hold the sensor state and data set. // Use variables to hold the sensor state and data set.
Sensor.SensorState currentState = null; Sensor.SensorState currentState = null;
Sensor.SensorDataSet currentDataSet = null; Sensor.SensorDataSet currentDataSet = null;
ITrackRecordingService service = serviceConnection.getServiceIfBound(); ITrackRecordingService service = serviceConnection.getServiceIfBound();
// If a temp sensor manager is present, shut it down, // If a temp sensor manager is present, shut it down,
// probably recording just started. // probably recording just started.
stopTempSensorManager(); stopTempSensorManager();
@@ -208,7 +206,7 @@ public class SensorStateActivity extends Activity {
} catch (InvalidProtocolBufferException e) { } catch (InvalidProtocolBufferException e) {
Log.e(TAG, "Could not read sensor data.", e); Log.e(TAG, "Could not read sensor data.", e);
} }
try { try {
currentState = Sensor.SensorState.valueOf(service.getSensorState()); currentState = Sensor.SensorState.valueOf(service.getSensorState());
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -220,17 +218,17 @@ public class SensorStateActivity extends Activity {
// Update the sensor state, and sensor data, using the variables. // Update the sensor state, and sensor data, using the variables.
updateSensorStateAndData(currentState, currentDataSet); updateSensorStateAndData(currentState, currentDataSet);
} }
/** /**
* Stops the temporary sensor manager, if one exists. * Stops the temporary sensor manager, if one exists.
*/ */
private void stopTempSensorManager() { private void stopTempSensorManager() {
if (tempSensorManager != null) { if (tempSensorManager != null) {
tempSensorManager.shutdown(); SensorManagerFactory.getInstance().releaseSensorManager(tempSensorManager);
tempSensorManager = null; tempSensorManager = null;
} }
} }
private void updateSensorStateAndData(Sensor.SensorState state, Sensor.SensorDataSet dataSet) { private void updateSensorStateAndData(Sensor.SensorState state, Sensor.SensorDataSet dataSet) {
updateSensorState(state == null ? Sensor.SensorState.NONE : state); updateSensorState(state == null ? Sensor.SensorState.NONE : state);
updateSensorData(dataSet); updateSensorData(dataSet);
@@ -296,7 +296,7 @@ public class TrackRecordingService extends Service {
handleStartCommand(intent, startId); handleStartCommand(intent, startId);
return START_STICKY; return START_STICKY;
} }
private void handleStartCommand(Intent intent, int startId) { private void handleStartCommand(Intent intent, int startId) {
Log.d(TAG, "TrackRecordingService.handleStartCommand: " + startId); Log.d(TAG, "TrackRecordingService.handleStartCommand: " + startId);
@@ -313,7 +313,7 @@ public class TrackRecordingService extends Service {
private boolean isTrackInProgress() { private boolean isTrackInProgress() {
return recordingTrackId != -1 || isRecording; return recordingTrackId != -1 || isRecording;
} }
private void resumeTrack(int startId) { private void resumeTrack(int startId) {
Log.d(TAG, "TrackRecordingService: requested resume"); Log.d(TAG, "TrackRecordingService: requested resume");
@@ -358,7 +358,7 @@ public class TrackRecordingService extends Service {
unregisterLocationListener(); unregisterLocationListener();
shutdownTaskExecutors(); shutdownTaskExecutors();
if (sensorManager != null) { if (sensorManager != null) {
sensorManager.shutdown(); SensorManagerFactory.getInstance().releaseSensorManager(sensorManager);
sensorManager = null; sensorManager = null;
} }
@@ -499,12 +499,12 @@ public class TrackRecordingService extends Service {
protected void startForegroundService(Notification notification) { protected void startForegroundService(Notification notification) {
startForeground(1, notification); startForeground(1, notification);
} }
@VisibleForTesting @VisibleForTesting
protected void stopForegroundService() { protected void stopForegroundService() {
stopForeground(true); stopForeground(true);
} }
private void setUpTaskExecutors() { private void setUpTaskExecutors() {
announcementExecutor = new PeriodicTaskExecutor(this, new StatusAnnouncerFactory()); announcementExecutor = new PeriodicTaskExecutor(this, new StatusAnnouncerFactory());
splitExecutor = new PeriodicTaskExecutor(this, new SplitTask.Factory()); splitExecutor = new PeriodicTaskExecutor(this, new SplitTask.Factory());
@@ -559,7 +559,7 @@ public class TrackRecordingService extends Service {
Log.d(TAG, Log.d(TAG,
"Location listener now unregistered w/ TrackRecordingService."); "Location listener now unregistered w/ TrackRecordingService.");
} }
private String getDefaultActivityType(Context context) { private String getDefaultActivityType(Context context) {
SharedPreferences prefs = context.getSharedPreferences( SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE); Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
@@ -601,10 +601,7 @@ public class TrackRecordingService extends Service {
length = 0; length = 0;
showNotification(); showNotification();
registerLocationListener(); registerLocationListener();
sensorManager = SensorManagerFactory.getSensorManager(this); sensorManager = SensorManagerFactory.getInstance().getSensorManager(this);
if (sensorManager != null) {
sensorManager.onStartTrack();
}
// Reset the number of auto-resume retries. // Reset the number of auto-resume retries.
setAutoResumeTrackRetries(0); setAutoResumeTrackRetries(0);
@@ -1038,7 +1035,7 @@ public class TrackRecordingService extends Service {
prefManager.setRecordingTrack(recordingTrackId = -1); prefManager.setRecordingTrack(recordingTrackId = -1);
if (sensorManager != null) { if (sensorManager != null) {
sensorManager.shutdown(); SensorManagerFactory.getInstance().releaseSensorManager(sensorManager);
sensorManager = null; sensorManager = null;
} }
@@ -1056,7 +1053,7 @@ public class TrackRecordingService extends Service {
.setAction(getString(actionResId)) .setAction(getString(actionResId))
.putExtra(getString(R.string.track_id_broadcast_extra), trackId); .putExtra(getString(R.string.track_id_broadcast_extra), trackId);
sendBroadcast(broadcastIntent, getString(R.string.permission_notification_value)); sendBroadcast(broadcastIntent, getString(R.string.permission_notification_value));
SharedPreferences sharedPreferences = getSharedPreferences( SharedPreferences sharedPreferences = getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE); Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (sharedPreferences.getBoolean(getString(R.string.allow_access_key), false)) { if (sharedPreferences.getBoolean(getString(R.string.allow_access_key), false)) {
@@ -1202,17 +1199,17 @@ public class TrackRecordingService extends Service {
throw new IllegalStateException("The service has been already detached!"); throw new IllegalStateException("The service has been already detached!");
} }
} }
/** /**
* Returns true if the RPC caller is from the same application or if the * Returns true if the RPC caller is from the same application or if the
* "Allow access" setting indicates that another app can invoke this service's * "Allow access" setting indicates that another app can invoke this service's
* RPCs. * RPCs.
*/ */
private boolean canAccess() { private boolean canAccess() {
// As a precondition for access, must check if the service is available. // As a precondition for access, must check if the service is available.
checkService(); checkService();
if (Process.myPid() == Binder.getCallingPid()) { if (Process.myPid() == Binder.getCallingPid()) {
return true; return true;
} else { } else {
@@ -1297,7 +1294,7 @@ public class TrackRecordingService extends Service {
public int getSensorState() { public int getSensorState() {
if (!canAccess()) { if (!canAccess()) {
return Sensor.SensorState.NONE.getNumber(); return Sensor.SensorState.NONE.getNumber();
} }
if (service.sensorManager == null) { if (service.sensorManager == null) {
Log.d(TAG, "No sensor manager for data."); Log.d(TAG, "No sensor manager for data.");
return Sensor.SensorState.NONE.getNumber(); return Sensor.SensorState.NONE.getNumber();
@@ -31,15 +31,28 @@ import android.util.Log;
*/ */
public class SensorManagerFactory { public class SensorManagerFactory {
private String activeSensorType;
private SensorManager activeSensorManager;
private int refCount;
private static SensorManagerFactory instance = new SensorManagerFactory();
private SensorManagerFactory() { private SensorManagerFactory() {
} }
/** /**
* Get a new sensor manager. * Get the factory instance.
*/
public static SensorManagerFactory getInstance() {
return instance;
}
/**
* Get and start a new sensor manager.
* @param context Context to fetch system preferences. * @param context Context to fetch system preferences.
* @return The sensor manager that corresponds to the sensor type setting. * @return The sensor manager that corresponds to the sensor type setting.
*/ */
public static SensorManager getSensorManager(Context context) { public SensorManager getSensorManager(Context context) {
SharedPreferences prefs = context.getSharedPreferences( SharedPreferences prefs = context.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE); Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
if (prefs == null) { if (prefs == null) {
@@ -52,18 +65,54 @@ public class SensorManagerFactory {
Log.i(Constants.TAG, "Creating sensor of type: " + sensor); Log.i(Constants.TAG, "Creating sensor of type: " + sensor);
if (sensor == null) { if (sensor == null) {
reset();
return null; return null;
} else if (sensor.equals(context.getString(R.string.sensor_type_value_ant))) { }
return new AntDirectSensorManager(context); if (sensor.equals(activeSensorType)) {
Log.i(Constants.TAG, "Returning existing sensor manager.");
refCount++;
return activeSensorManager;
}
reset();
if (sensor.equals(context.getString(R.string.sensor_type_value_ant))) {
activeSensorManager = new AntDirectSensorManager(context);
} else if (sensor.equals(context.getString(R.string.sensor_type_value_srm_ant_bridge))) { } else if (sensor.equals(context.getString(R.string.sensor_type_value_srm_ant_bridge))) {
return new AntSrmBridgeSensorManager(context); activeSensorManager = new AntSrmBridgeSensorManager(context);
} else if (sensor.equals(context.getString(R.string.sensor_type_value_zephyr))) { } else if (sensor.equals(context.getString(R.string.sensor_type_value_zephyr))) {
return new ZephyrSensorManager(context); activeSensorManager = new ZephyrSensorManager(context);
} else if (sensor.equals(context.getString(R.string.sensor_type_value_polar))) { } else if (sensor.equals(context.getString(R.string.sensor_type_value_polar))) {
return new PolarSensorManager(context); activeSensorManager = new PolarSensorManager(context);
} else { } else {
Log.w(Constants.TAG, "Unable to find sensor type: " + sensor); Log.w(Constants.TAG, "Unable to find sensor type: " + sensor);
return null; return null;
} }
activeSensorType = sensor;
refCount = 1;
activeSensorManager.onStartTrack();
return activeSensorManager;
}
/**
* Finish using a sensor manager.
*/
public void releaseSensorManager(SensorManager sensorManager) {
Log.i(Constants.TAG, "releaseSensorManager: " + activeSensorType + " " + refCount);
if (sensorManager != activeSensorManager) {
Log.e(Constants.TAG, "invalid parameter to releaseSensorManager");
}
if (--refCount > 0) {
return;
}
reset();
}
private void reset() {
activeSensorType = null;
if (activeSensorManager != null) {
activeSensorManager.shutdown();
}
activeSensorManager = null;
refCount = 0;
} }
} }
@@ -17,23 +17,23 @@ public class SensorManagerFactoryTest extends AndroidTestCase {
@Override @Override
protected void setUp() throws Exception { protected void setUp() throws Exception {
super.setUp(); super.setUp();
sharedPreferences = getContext().getSharedPreferences( sharedPreferences = getContext().getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE); Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
// Let's use default values. // Let's use default values.
sharedPreferences.edit().clear().apply(); sharedPreferences.edit().clear().apply();
} }
@SmallTest @SmallTest
public void testDefaultSettings() throws Exception { public void testDefaultSettings() throws Exception {
assertNull(SensorManagerFactory.getSensorManager(getContext())); assertNull(SensorManagerFactory.getInstance().getSensorManager(getContext()));
} }
@SmallTest @SmallTest
public void testCreateZephyr() throws Exception { public void testCreateZephyr() throws Exception {
assertClassForName(ZephyrSensorManager.class, R.string.sensor_type_value_zephyr); assertClassForName(ZephyrSensorManager.class, R.string.sensor_type_value_zephyr);
} }
@SmallTest @SmallTest
public void testCreateAnt() throws Exception { public void testCreateAnt() throws Exception {
assertClassForName(AntDirectSensorManager.class, R.string.sensor_type_value_ant); assertClassForName(AntDirectSensorManager.class, R.string.sensor_type_value_ant);
@@ -49,8 +49,9 @@ public class SensorManagerFactoryTest extends AndroidTestCase {
.putString(getContext().getString(R.string.sensor_type_key), .putString(getContext().getString(R.string.sensor_type_key),
getContext().getString(i)) getContext().getString(i))
.apply(); .apply();
SensorManager sm = SensorManagerFactory.getSensorManager(getContext()); SensorManager sm = SensorManagerFactory.getInstance().getSensorManager(getContext());
assertNotNull(sm); assertNotNull(sm);
assertTrue(c.isInstance(sm)); assertTrue(c.isInstance(sm));
SensorManagerFactory.getInstance().releaseSensorManager(sm);
} }
} }