From b3dc5eb4e4143b119491a05e89b186763979ef75 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 3 Feb 2010 19:17:18 -0800 Subject: [PATCH] fix [2313526] sensor enable race condition Make sure we wait until the SensorThread is running an has open the sensors fd. Also handle errors when/if this fails. --- core/java/android/hardware/SensorManager.java | 52 +++++++++++++------ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index 0c6bb1afd2c40..8eed9f7341a85 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -287,6 +287,7 @@ public class SensorManager static private class SensorThread { Thread mThread; + boolean mSensorsReady; SensorThread() { // this gets to the sensor module. We can have only one per process. @@ -299,17 +300,28 @@ public class SensorManager } // must be called with sListeners lock - void startLocked(ISensorService service) { + boolean startLocked(ISensorService service) { try { if (mThread == null) { Bundle dataChannel = service.getDataChannel(); - mThread = new Thread(new SensorThreadRunnable(dataChannel), - SensorThread.class.getName()); - mThread.start(); + if (dataChannel != null) { + mSensorsReady = false; + SensorThreadRunnable runnable = new SensorThreadRunnable(dataChannel); + Thread thread = new Thread(runnable, SensorThread.class.getName()); + thread.start(); + synchronized (runnable) { + while (mSensorsReady == false) { + runnable.wait(); + } + } + mThread = thread; + } } } catch (RemoteException e) { Log.e(TAG, "RemoteException in startLocked: ", e); + } catch (InterruptedException e) { } + return mThread == null ? false : true; } private class SensorThreadRunnable implements Runnable { @@ -319,13 +331,9 @@ public class SensorManager } private boolean open() { - if (mDataChannel == null) { - Log.e(TAG, "mDataChannel == NULL, exiting"); - synchronized (sListeners) { - mThread = null; - } - return false; - } + // NOTE: this cannot synchronize on sListeners, since + // it's held in the main thread at least until we + // return from here. // this thread is guaranteed to be unique Parcelable[] pfds = mDataChannel.getParcelableArray("fds"); @@ -370,6 +378,12 @@ public class SensorManager return; } + synchronized (this) { + // we've open the driver, we're ready to open the sensors + mSensorsReady = true; + this.notify(); + } + while (true) { // wait for an event final int sensor = sensors_data_poll(values, status, timestamp); @@ -907,14 +921,18 @@ public class SensorManager String name = sensor.getName(); int handle = sensor.getHandle(); if (l == null) { + result = false; l = new ListenerDelegate(listener, sensor, handler); - result = mSensorService.enableSensor(l, name, handle, delay); - if (result) { - sListeners.add(l); - sListeners.notify(); - } + sListeners.add(l); if (!sListeners.isEmpty()) { - sSensorThread.startLocked(mSensorService); + result = sSensorThread.startLocked(mSensorService); + if (result) { + result = mSensorService.enableSensor(l, name, handle, delay); + if (!result) { + // there was an error, remove the listeners + sListeners.remove(l); + } + } } } else { result = mSensorService.enableSensor(l, name, handle, delay);