OSDN Git Service

fix [2313526] sensor enable race condition
authorMathias Agopian <mathias@google.com>
Thu, 4 Feb 2010 03:17:18 +0000 (19:17 -0800)
committerMathias Agopian <mathias@google.com>
Thu, 4 Feb 2010 23:25:05 +0000 (15:25 -0800)
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

index 0c6bb1a..8eed9f7 100644 (file)
@@ -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);