resolve merge conflicts of 13c5c34 to mnc-dev am: 79b74d787d am: abe293b950
am: 02e4440eab

Change-Id: I66e7e982176555f09bf298325754d708ef0ecac0
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 9a5a81e..55282cf 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -93,6 +93,7 @@
     { "sched",      "CPU Scheduling",   0, {
         { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
         { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/sched/sched_blocked_reason/enable" },
     } },
     { "irq",        "IRQ Events",   0, {
         { REQ,      "/sys/kernel/debug/tracing/events/irq/enable" },
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index b88b605..a2e4f4b 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -262,6 +262,8 @@
 
 /* End copy from system/core/logd/LogBuffer.cpp */
 
+static const unsigned long logcat_min_timeout = 40000; /* ms */
+
 /* dumps the current system state to stdout */
 static void dumpstate() {
     unsigned long timeout;
@@ -334,18 +336,18 @@
     // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
     // calculate timeout
     timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
-    if (timeout < 20000) {
-        timeout = 20000;
+    if (timeout < logcat_min_timeout) {
+        timeout = logcat_min_timeout;
     }
     run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime", "-d", "*:v", NULL);
     timeout = logcat_timeout("events");
-    if (timeout < 20000) {
-        timeout = 20000;
+    if (timeout < logcat_min_timeout) {
+        timeout = logcat_min_timeout;
     }
     run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events", "-v", "threadtime", "-d", "*:v", NULL);
     timeout = logcat_timeout("radio");
-    if (timeout < 20000) {
-        timeout = 20000;
+    if (timeout < logcat_min_timeout) {
+        timeout = logcat_min_timeout;
     }
     run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL);
 
diff --git a/include/gui/SensorManager.h b/include/gui/SensorManager.h
index f039caf..0cff46c 100644
--- a/include/gui/SensorManager.h
+++ b/include/gui/SensorManager.h
@@ -22,11 +22,9 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <binder/BinderService.h>
 #include <binder/IBinder.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
-#include <binder/PermissionCache.h>
 
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
@@ -56,8 +54,7 @@
     static SensorManager& getInstanceForPackage(const String16& packageName);
     ~SensorManager();
 
-    ssize_t getSensorList(Sensor const* const** list);
-    ssize_t getAvailableSensorList(Sensor const* const** list);
+    ssize_t getSensorList(Sensor const* const** list) const;
     Sensor const* getDefaultSensor(int type);
     sp<SensorEventQueue> createEventQueue(String8 packageName = String8(""), int mode = 0);
     bool isDataInjectionEnabled();
@@ -67,27 +64,18 @@
     void sensorManagerDied();
 
     SensorManager(const String16& opPackageName);
-    status_t assertStateLocked();
-    void updateAvailableSensorList();
+    status_t assertStateLocked() const;
 
 private:
     static Mutex sLock;
     static std::map<String16, SensorManager*> sPackageInstances;
 
-    Mutex mLock;
-    sp<ISensorServer> mSensorServer;
-
-    // for Java API
-    Sensor const** mSensorList;
-
-    // for NDK API
-    Sensor const** mAvailableSensorList;
-    ssize_t mNumAvailableSensor;
-
-    Vector<Sensor> mSensors;
-    sp<IBinder::DeathRecipient> mDeathObserver;
+    mutable Mutex mLock;
+    mutable sp<ISensorServer> mSensorServer;
+    mutable Sensor const** mSensorList;
+    mutable Vector<Sensor> mSensors;
+    mutable sp<IBinder::DeathRecipient> mDeathObserver;
     const String16 mOpPackageName;
-    bool mBodyPermission;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp
index 4277032..33608b5 100644
--- a/libs/gui/SensorManager.cpp
+++ b/libs/gui/SensorManager.cpp
@@ -89,8 +89,7 @@
 }
 
 SensorManager::SensorManager(const String16& opPackageName)
-    : mSensorList(NULL), mAvailableSensorList(NULL), mNumAvailableSensor(0),
-      mOpPackageName(opPackageName), mBodyPermission(false)
+    : mSensorList(0), mOpPackageName(opPackageName)
 {
     // okay we're not locked here, but it's not needed during construction
     assertStateLocked();
@@ -99,9 +98,6 @@
 SensorManager::~SensorManager()
 {
     free(mSensorList);
-    if (mAvailableSensorList) {
-        free(mAvailableSensorList);
-    }
 }
 
 void SensorManager::sensorManagerDied()
@@ -110,14 +106,10 @@
     mSensorServer.clear();
     free(mSensorList);
     mSensorList = NULL;
-    if (mAvailableSensorList) {
-        free(mAvailableSensorList);
-        mAvailableSensorList = NULL;
-    }
     mSensors.clear();
 }
 
-status_t SensorManager::assertStateLocked() {
+status_t SensorManager::assertStateLocked() const {
     bool initSensorManager = false;
     if (mSensorServer == NULL) {
         initSensorManager = true;
@@ -167,14 +159,13 @@
         for (size_t i=0 ; i<count ; i++) {
             mSensorList[i] = mSensors.array() + i;
         }
-
-        updateAvailableSensorList();
     }
 
     return NO_ERROR;
 }
 
-ssize_t SensorManager::getSensorList(Sensor const* const** list) {
+ssize_t SensorManager::getSensorList(Sensor const* const** list) const
+{
     Mutex::Autolock _l(mLock);
     status_t err = assertStateLocked();
     if (err < 0) {
@@ -184,76 +175,10 @@
     return static_cast<ssize_t>(mSensors.size());
 }
 
-void SensorManager::updateAvailableSensorList() {
-    const int uid = static_cast<int>(IPCThreadState::self()->getCallingUid());
-    const int pid = static_cast<int>(IPCThreadState::self()->getCallingPid());
-    const String16 BODY_SENSOR_PERMISSION("android.permission.BODY_SENSORS");
-    const String8 BODY_SENSOR_PERMISSION8("android.permission.BODY_SENSORS");
-
-    bool bodySensorPermission = false;
-
-    sp<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
-    if (binder != NULL) {
-        bodySensorPermission = interface_cast<IPermissionController>(binder)->
-                checkPermission(BODY_SENSOR_PERMISSION, pid, uid);
-    }
-
-    // only update if app got BODY_SENSORS permission after last call or the sensor list has not
-    // been populated.
-    //
-    // it is not possible for the reverse transition, as the app will be killed when permission is
-    // revoked.
-    if ( (bodySensorPermission && !mBodyPermission) || mAvailableSensorList == NULL) {
-
-        // allocate only when necessary
-        if (mAvailableSensorList == NULL) {
-            // allocate a list big enough to fit all sensors (including those requires permission
-            // that the app do not have;
-            mAvailableSensorList =
-                    static_cast<Sensor const**>(malloc(mSensors.size() * sizeof(Sensor*)));
-
-            // first populate all sensors that do not need body sensor permission
-            ssize_t& n = mNumAvailableSensor;
-            for (size_t i = 0; i < mSensors.size() ; i++) {
-                if (mSensors[i].getRequiredPermission() != BODY_SENSOR_PERMISSION8) {
-                    mAvailableSensorList[n++] = mSensors.array() + i;
-                }
-            }
-        }
-
-        if (bodySensorPermission) {
-            // if the app just got the sensor permission back, fill the sensor at the end of list
-            ssize_t& n = mNumAvailableSensor;
-            for (size_t i = 0; i < mSensors.size() ; i++) {
-                if (mSensors[i].getRequiredPermission() == BODY_SENSOR_PERMISSION8) {
-                    mAvailableSensorList[n++] = mSensors.array() + i;
-                }
-            }
-        }
-
-        mBodyPermission = bodySensorPermission;
-    }
-}
-
-ssize_t SensorManager::getAvailableSensorList(Sensor const* const** list) {
-    Mutex::Autolock _l(mLock);
-    status_t err = assertStateLocked();
-    if (err < 0) {
-        return static_cast<ssize_t>(err);
-    }
-
-    updateAvailableSensorList();
-
-    *list = mAvailableSensorList;
-    return mNumAvailableSensor;
-}
-
-Sensor const* SensorManager::getDefaultSensor(int type) {
+Sensor const* SensorManager::getDefaultSensor(int type)
+{
     Mutex::Autolock _l(mLock);
     if (assertStateLocked() == NO_ERROR) {
-
-        updateAvailableSensorList();
-
         bool wakeUpSensor = false;
         // For the following sensor types, return a wake-up sensor. These types are by default
         // defined as wake-up sensors. For the rest of the sensor types defined in sensors.h return
@@ -267,9 +192,9 @@
         // in the future it will make sense to let the SensorService make
         // that decision.
         for (size_t i=0 ; i<mSensors.size() ; i++) {
-            if (mAvailableSensorList[i]->getType() == type &&
-                mAvailableSensorList[i]->isWakeUpSensor() == wakeUpSensor) {
-                return mAvailableSensorList[i];
+            if (mSensorList[i]->getType() == type &&
+                mSensorList[i]->isWakeUpSensor() == wakeUpSensor) {
+                return mSensorList[i];
             }
         }
     }
diff --git a/services/sensorservice/CorrectedGyroSensor.cpp b/services/sensorservice/CorrectedGyroSensor.cpp
index 7b1f346..b07d544 100644
--- a/services/sensorservice/CorrectedGyroSensor.cpp
+++ b/services/sensorservice/CorrectedGyroSensor.cpp
@@ -58,12 +58,12 @@
 
 status_t CorrectedGyroSensor::activate(void* ident, bool enabled) {
     mSensorDevice.activate(ident, mGyro.getHandle(), enabled);
-    return mSensorFusion.activate(FUSION_9AXIS, ident, enabled);
+    return mSensorFusion.activate(ident, enabled);
 }
 
 status_t CorrectedGyroSensor::setDelay(void* ident, int /*handle*/, int64_t ns) {
     mSensorDevice.setDelay(ident, mGyro.getHandle(), ns);
-    return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
+    return mSensorFusion.setDelay(ident, ns);
 }
 
 Sensor CorrectedGyroSensor::getSensor() const {
diff --git a/services/sensorservice/Fusion.cpp b/services/sensorservice/Fusion.cpp
index 359d289..4f63c31 100644
--- a/services/sensorservice/Fusion.cpp
+++ b/services/sensorservice/Fusion.cpp
@@ -24,44 +24,28 @@
 
 // -----------------------------------------------------------------------
 
-/*==================== BEGIN FUSION SENSOR PARAMETER =========================*/
-
-/* Note:
- *   If a platform uses software fusion, it is necessary to tune the following
- *   parameters to fit the hardware sensors prior to release.
- *
- *   The DEFAULT_ parameters will be used in FUSION_9AXIS and FUSION_NOMAG mode.
- *   The GEOMAG_ parameters will be used in FUSION_NOGYRO mode.
- */
-
 /*
- * GYRO_VAR gives the measured variance of the gyro's output per
+ * gyroVAR gives the measured variance of the gyro's output per
  * Hz (or variance at 1 Hz). This is an "intrinsic" parameter of the gyro,
  * which is independent of the sampling frequency.
  *
  * The variance of gyro's output at a given sampling period can be
  * calculated as:
- *      variance(T) = GYRO_VAR / T
+ *      variance(T) = gyroVAR / T
  *
  * The variance of the INTEGRATED OUTPUT at a given sampling period can be
  * calculated as:
- *       variance_integrate_output(T) = GYRO_VAR * T
+ *       variance_integrate_output(T) = gyroVAR * T
+ *
  */
-static const float DEFAULT_GYRO_VAR = 1e-7;      // (rad/s)^2 / Hz
-static const float DEFAULT_GYRO_BIAS_VAR = 1e-12;  // (rad/s)^2 / s (guessed)
-static const float GEOMAG_GYRO_VAR = 1e-4;      // (rad/s)^2 / Hz
-static const float GEOMAG_GYRO_BIAS_VAR = 1e-8;  // (rad/s)^2 / s (guessed)
+static const float gyroVAR = 1e-7;      // (rad/s)^2 / Hz
+static const float biasVAR = 1e-8;      // (rad/s)^2 / s (guessed)
 
 /*
  * Standard deviations of accelerometer and magnetometer
  */
-static const float DEFAULT_ACC_STDEV  = 0.015f; // m/s^2 (measured 0.08 / CDD 0.05)
-static const float DEFAULT_MAG_STDEV  = 0.1f;   // uT    (measured 0.7  / CDD 0.5)
-static const float GEOMAG_ACC_STDEV  = 0.05f; // m/s^2 (measured 0.08 / CDD 0.05)
-static const float GEOMAG_MAG_STDEV  = 0.1f;   // uT    (measured 0.7  / CDD 0.5)
-
-
-/* ====================== END FUSION SENSOR PARAMETER ========================*/
+static const float accSTDEV  = 0.05f;   // m/s^2 (measured 0.08 / CDD 0.05)
+static const float magSTDEV  = 0.5f;    // uT    (measured 0.7  / CDD 0.5)
 
 static const float SYMMETRY_TOLERANCE = 1e-10f;
 
@@ -70,8 +54,7 @@
  * ill-conditioning and div by zeros.
  * Threshhold: 10% of g, in m/s^2
  */
-static const float NOMINAL_GRAVITY = 9.81f;
-static const float FREE_FALL_THRESHOLD = 0.1f * (NOMINAL_GRAVITY);
+static const float FREE_FALL_THRESHOLD = 0.981f;
 static const float FREE_FALL_THRESHOLD_SQ =
         FREE_FALL_THRESHOLD*FREE_FALL_THRESHOLD;
 
@@ -104,9 +87,6 @@
 static const float MIN_VALID_CROSS_PRODUCT_MAG_SQ =
     MIN_VALID_CROSS_PRODUCT_MAG*MIN_VALID_CROSS_PRODUCT_MAG;
 
-static const float W_EPS = 1e-4f;
-static const float SQRT_3 = 1.732f;
-static const float WVEC_EPS = 1e-4f/SQRT_3;
 // -----------------------------------------------------------------------
 
 template <typename TYPE, size_t C, size_t R>
@@ -193,7 +173,7 @@
     init();
 }
 
-void Fusion::init(int mode) {
+void Fusion::init() {
     mInitState = 0;
 
     mGyroRate = 0;
@@ -203,19 +183,6 @@
     mCount[2] = 0;
 
     mData = 0;
-    mMode = mode;
-
-    if (mMode != FUSION_NOGYRO) { //normal or game rotation
-        mParam.gyroVar = DEFAULT_GYRO_VAR;
-        mParam.gyroBiasVar = DEFAULT_GYRO_BIAS_VAR;
-        mParam.accStdev = DEFAULT_ACC_STDEV;
-        mParam.magStdev = DEFAULT_MAG_STDEV;
-    } else {
-        mParam.gyroVar = GEOMAG_GYRO_VAR;
-        mParam.gyroBiasVar = GEOMAG_GYRO_BIAS_VAR;
-        mParam.accStdev = GEOMAG_ACC_STDEV;
-        mParam.magStdev = GEOMAG_MAG_STDEV;
-    }
 }
 
 void Fusion::initFusion(const vec4_t& q, float dT)
@@ -238,11 +205,11 @@
     const float dT3 = dT2*dT;
 
     // variance of integrated output at 1/dT Hz (random drift)
-    const float q00 = mParam.gyroVar * dT + 0.33333f * mParam.gyroBiasVar * dT3;
+    const float q00 = gyroVAR * dT + 0.33333f * biasVAR * dT3;
 
     // variance of drift rate ramp
-    const float q11 = mParam.gyroBiasVar * dT;
-    const float q10 = 0.5f * mParam.gyroBiasVar * dT2;
+    const float q11 = biasVAR * dT;
+    const float q10 = 0.5f * biasVAR * dT2;
     const float q01 = q10;
 
     GQGt[0][0] =  q00;      // rad^2
@@ -256,9 +223,7 @@
 }
 
 bool Fusion::hasEstimate() const {
-    return ((mInitState & MAG) || (mMode == FUSION_NOMAG)) &&
-           ((mInitState & GYRO) || (mMode == FUSION_NOGYRO)) &&
-           (mInitState & ACC);
+    return (mInitState == (MAG|ACC|GYRO));
 }
 
 bool Fusion::checkInitComplete(int what, const vec3_t& d, float dT) {
@@ -269,9 +234,6 @@
         mData[0] += d * (1/length(d));
         mCount[0]++;
         mInitState |= ACC;
-        if (mMode == FUSION_NOGYRO ) {
-            mGyroRate = dT;
-        }
     } else if (what == MAG) {
         mData[1] += d * (1/length(d));
         mCount[1]++;
@@ -280,29 +242,25 @@
         mGyroRate = dT;
         mData[2] += d*dT;
         mCount[2]++;
-        mInitState |= GYRO;
+        if (mCount[2] == 64) {
+            // 64 samples is good enough to estimate the gyro drift and
+            // doesn't take too much time.
+            mInitState |= GYRO;
+        }
     }
 
-    if (hasEstimate()) {
+    if (mInitState == (MAG|ACC|GYRO)) {
         // Average all the values we collected so far
         mData[0] *= 1.0f/mCount[0];
-        if (mMode != FUSION_NOMAG) {
-            mData[1] *= 1.0f/mCount[1];
-        }
+        mData[1] *= 1.0f/mCount[1];
         mData[2] *= 1.0f/mCount[2];
 
         // calculate the MRPs from the data collection, this gives us
         // a rough estimate of our initial state
         mat33_t R;
-        vec3_t  up(mData[0]);
-        vec3_t  east;
-
-        if (mMode != FUSION_NOMAG) {
-            east = normalize(cross_product(mData[1], up));
-        } else {
-            east = getOrthogonal(up);
-        }
-
+        vec3_t up(mData[0]);
+        vec3_t east(cross_product(mData[1], up));
+        east *= 1/length(east);
         vec3_t north(cross_product(up, east));
         R << east << north << up;
         const vec4_t q = matrixToQuat(R);
@@ -320,43 +278,21 @@
     predict(w, dT);
 }
 
-status_t Fusion::handleAcc(const vec3_t& a, float dT) {
-    if (!checkInitComplete(ACC, a, dT))
-        return BAD_VALUE;
-
+status_t Fusion::handleAcc(const vec3_t& a) {
     // ignore acceleration data if we're close to free-fall
-    const float l = length(a);
-    if (l < FREE_FALL_THRESHOLD) {
+    if (length_squared(a) < FREE_FALL_THRESHOLD_SQ) {
         return BAD_VALUE;
     }
 
-    const float l_inv = 1.0f/l;
+    if (!checkInitComplete(ACC, a))
+        return BAD_VALUE;
 
-    if ( mMode == FUSION_NOGYRO ) {
-        //geo mag
-        vec3_t w_dummy;
-        w_dummy = x1; //bias
-        predict(w_dummy, dT);
-    }
-
-    if ( mMode == FUSION_NOMAG) {
-        vec3_t m;
-        m = getRotationMatrix()*Bm;
-        update(m, Bm, mParam.magStdev);
-    }
-
-    vec3_t unityA = a * l_inv;
-    const float d = sqrtf(fabsf(l- NOMINAL_GRAVITY));
-    const float p = l_inv * mParam.accStdev*expf(d);
-
-    update(unityA, Ba, p);
+    const float l = 1/length(a);
+    update(a*l, Ba, accSTDEV*l);
     return NO_ERROR;
 }
 
 status_t Fusion::handleMag(const vec3_t& m) {
-    if (!checkInitComplete(MAG, m))
-        return BAD_VALUE;
-
     // the geomagnetic-field should be between 30uT and 60uT
     // reject if too large to avoid spurious magnetic sources
     const float magFieldSq = length_squared(m);
@@ -368,6 +304,9 @@
         return BAD_VALUE;
     }
 
+    if (!checkInitComplete(MAG, m))
+        return BAD_VALUE;
+
     // Orthogonalize the magnetic field to the gravity field, mapping it into
     // tangent to Earth.
     const vec3_t up( getRotationMatrix() * Ba );
@@ -385,10 +324,10 @@
     // then pass it in as the update.
     vec3_t north( cross_product(up, east) );
 
-    const float l_inv = 1 / length(north);
-    north *= l_inv;
+    const float l = 1 / length(north);
+    north *= l;
 
-    update(north, Bm,  mParam.magStdev*l_inv);
+    update(north, Bm, magSTDEV*l);
     return NO_ERROR;
 }
 
@@ -433,11 +372,8 @@
 void Fusion::predict(const vec3_t& w, float dT) {
     const vec4_t q  = x0;
     const vec3_t b  = x1;
-    vec3_t we = w - b;
+    const vec3_t we = w - b;
 
-    if (length(we) < WVEC_EPS) {
-        we = (we[0]>0.f)?WVEC_EPS:-WVEC_EPS;
-    }
     // q(k+1) = O(we)*q(k)
     // --------------------
     //
@@ -470,7 +406,7 @@
     const mat33_t wx2(wx*wx);
     const float lwedT = length(we)*dT;
     const float hlwedT = 0.5f*lwedT;
-    const float ilwe = 1.f/length(we);
+    const float ilwe = 1/length(we);
     const float k0 = (1-cosf(lwedT))*(ilwe*ilwe);
     const float k1 = sinf(lwedT);
     const float k2 = cosf(hlwedT);
@@ -486,7 +422,6 @@
     Phi[1][0] = wx*k0 - I33dT - wx2*(ilwe*ilwe*ilwe)*(lwedT-k1);
 
     x0 = O*q;
-
     if (x0.w < 0)
         x0 = -x0;
 
@@ -531,37 +466,15 @@
 
     const vec3_t e(z - Bb);
     const vec3_t dq(K[0]*e);
+    const vec3_t db(K[1]*e);
 
     q += getF(q)*(0.5f*dq);
     x0 = normalize_quat(q);
-
-    if (mMode != FUSION_NOMAG) {
-        const vec3_t db(K[1]*e);
-        x1 += db;
-    }
+    x1 += db;
 
     checkState();
 }
 
-vec3_t Fusion::getOrthogonal(const vec3_t &v) {
-    vec3_t w;
-    if (fabsf(v[0])<= fabsf(v[1]) && fabsf(v[0]) <= fabsf(v[2]))  {
-        w[0]=0.f;
-        w[1] = v[2];
-        w[2] = -v[1];
-    } else if (fabsf(v[1]) <= fabsf(v[2])) {
-        w[0] = v[2];
-        w[1] = 0.f;
-        w[2] = -v[0];
-    }else {
-        w[0] = v[1];
-        w[1] = -v[0];
-        w[2] = 0.f;
-    }
-    return normalize(w);
-}
-
-
 // -----------------------------------------------------------------------
 
 }; // namespace android
diff --git a/services/sensorservice/Fusion.h b/services/sensorservice/Fusion.h
index 602779f..7062999 100644
--- a/services/sensorservice/Fusion.h
+++ b/services/sensorservice/Fusion.h
@@ -27,13 +27,6 @@
 
 typedef mat<float, 3, 4> mat34_t;
 
-enum FUSION_MODE{
-    FUSION_9AXIS, // use accel gyro mag
-    FUSION_NOMAG, // use accel gyro (game rotation, gravity)
-    FUSION_NOGYRO, // use accel mag (geomag rotation)
-    NUM_FUSION_MODE
-};
-
 class Fusion {
     /*
      * the state vector is made of two sub-vector containing respectively:
@@ -62,9 +55,9 @@
 
 public:
     Fusion();
-    void init(int mode = FUSION_9AXIS);
+    void init();
     void handleGyro(const vec3_t& w, float dT);
-    status_t handleAcc(const vec3_t& a, float dT);
+    status_t handleAcc(const vec3_t& a);
     status_t handleMag(const vec3_t& m);
     vec4_t getAttitude() const;
     vec3_t getBias() const;
@@ -72,21 +65,12 @@
     bool hasEstimate() const;
 
 private:
-    struct Parameter {
-        float gyroVar;
-        float gyroBiasVar;
-        float accStdev;
-        float magStdev;
-    } mParam;
-
     mat<mat33_t, 2, 2> Phi;
     vec3_t Ba, Bm;
     uint32_t mInitState;
     float mGyroRate;
     vec<vec3_t, 3> mData;
     size_t mCount[3];
-    int mMode;
-
     enum { ACC=0x1, MAG=0x2, GYRO=0x4 };
     bool checkInitComplete(int, const vec3_t& w, float d = 0);
     void initFusion(const vec4_t& q0, float dT);
@@ -94,7 +78,6 @@
     void predict(const vec3_t& w, float dT);
     void update(const vec3_t& z, const vec3_t& Bi, float sigma);
     static mat34_t getF(const vec4_t& p);
-    static vec3_t getOrthogonal(const vec3_t &v);
 };
 
 }; // namespace android
diff --git a/services/sensorservice/GravitySensor.cpp b/services/sensorservice/GravitySensor.cpp
index f8279d2..3cb3745 100644
--- a/services/sensorservice/GravitySensor.cpp
+++ b/services/sensorservice/GravitySensor.cpp
@@ -47,9 +47,9 @@
     const static double NS2S = 1.0 / 1000000000.0;
     if (event.type == SENSOR_TYPE_ACCELEROMETER) {
         vec3_t g;
-        if (!mSensorFusion.hasEstimate(FUSION_NOMAG))
+        if (!mSensorFusion.hasEstimate())
             return false;
-        const mat33_t R(mSensorFusion.getRotationMatrix(FUSION_NOMAG));
+        const mat33_t R(mSensorFusion.getRotationMatrix());
         // FIXME: we need to estimate the length of gravity because
         // the accelerometer may have a small scaling error. This
         // translates to an offset in the linear-acceleration sensor.
@@ -67,11 +67,11 @@
 }
 
 status_t GravitySensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(FUSION_NOMAG, ident, enabled);
+    return mSensorFusion.activate(ident, enabled);
 }
 
 status_t GravitySensor::setDelay(void* ident, int /*handle*/, int64_t ns) {
-    return mSensorFusion.setDelay(FUSION_NOMAG, ident, ns);
+    return mSensorFusion.setDelay(ident, ns);
 }
 
 Sensor GravitySensor::getSensor() const {
diff --git a/services/sensorservice/OrientationSensor.cpp b/services/sensorservice/OrientationSensor.cpp
index d55f336..6d85cca 100644
--- a/services/sensorservice/OrientationSensor.cpp
+++ b/services/sensorservice/OrientationSensor.cpp
@@ -66,11 +66,11 @@
 }
 
 status_t OrientationSensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(FUSION_9AXIS, ident, enabled);
+    return mSensorFusion.activate(ident, enabled);
 }
 
 status_t OrientationSensor::setDelay(void* ident, int /*handle*/, int64_t ns) {
-    return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
+    return mSensorFusion.setDelay(ident, ns);
 }
 
 Sensor OrientationSensor::getSensor() const {
diff --git a/services/sensorservice/RotationVectorSensor.cpp b/services/sensorservice/RotationVectorSensor.cpp
index 238845b..cb305eb 100644
--- a/services/sensorservice/RotationVectorSensor.cpp
+++ b/services/sensorservice/RotationVectorSensor.cpp
@@ -27,10 +27,9 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-RotationVectorSensor::RotationVectorSensor(int mode)
+RotationVectorSensor::RotationVectorSensor()
     : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance()),
-      mMode(mode)
+      mSensorFusion(SensorFusion::getInstance())
 {
 }
 
@@ -38,15 +37,15 @@
         const sensors_event_t& event)
 {
     if (event.type == SENSOR_TYPE_ACCELEROMETER) {
-        if (mSensorFusion.hasEstimate(mMode)) {
-            const vec4_t q(mSensorFusion.getAttitude(mMode));
+        if (mSensorFusion.hasEstimate()) {
+            const vec4_t q(mSensorFusion.getAttitude());
             *outEvent = event;
             outEvent->data[0] = q.x;
             outEvent->data[1] = q.y;
             outEvent->data[2] = q.z;
             outEvent->data[3] = q.w;
-            outEvent->sensor = getSensorToken();
-            outEvent->type = getSensorType();
+            outEvent->sensor = '_rov';
+            outEvent->type = SENSOR_TYPE_ROTATION_VECTOR;
             return true;
         }
     }
@@ -54,20 +53,20 @@
 }
 
 status_t RotationVectorSensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(mMode, ident, enabled);
+    return mSensorFusion.activate(ident, enabled);
 }
 
 status_t RotationVectorSensor::setDelay(void* ident, int /*handle*/, int64_t ns) {
-    return mSensorFusion.setDelay(mMode, ident, ns);
+    return mSensorFusion.setDelay(ident, ns);
 }
 
 Sensor RotationVectorSensor::getSensor() const {
     sensor_t hwSensor;
-    hwSensor.name       = getSensorName();
+    hwSensor.name       = "Rotation Vector Sensor";
     hwSensor.vendor     = "AOSP";
     hwSensor.version    = 3;
-    hwSensor.handle     = getSensorToken();
-    hwSensor.type       = getSensorType();
+    hwSensor.handle     = '_rov';
+    hwSensor.type       = SENSOR_TYPE_ROTATION_VECTOR;
     hwSensor.maxRange   = 1;
     hwSensor.resolution = 1.0f / (1<<24);
     hwSensor.power      = mSensorFusion.getPowerUsage();
@@ -76,48 +75,6 @@
     return sensor;
 }
 
-int RotationVectorSensor::getSensorType() const {
-    switch(mMode) {
-        case FUSION_9AXIS:
-            return SENSOR_TYPE_ROTATION_VECTOR;
-        case FUSION_NOMAG:
-            return SENSOR_TYPE_GAME_ROTATION_VECTOR;
-        case FUSION_NOGYRO:
-            return SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR;
-        default:
-            assert(0);
-            return 0;
-    }
-}
-
-const char* RotationVectorSensor::getSensorName() const {
-    switch(mMode) {
-        case FUSION_9AXIS:
-            return "Rotation Vector Sensor";
-        case FUSION_NOMAG:
-            return "Game Rotation Vector Sensor";
-        case FUSION_NOGYRO:
-            return "GeoMag Rotation Vector Sensor";
-        default:
-            assert(0);
-            return NULL;
-    }
-}
-
-int RotationVectorSensor::getSensorToken() const {
-    switch(mMode) {
-        case FUSION_9AXIS:
-            return '_rov';
-        case FUSION_NOMAG:
-            return '_gar';
-        case FUSION_NOGYRO:
-            return '_geo';
-        default:
-            assert(0);
-            return 0;
-    }
-}
-
 // ---------------------------------------------------------------------------
 
 GyroDriftSensor::GyroDriftSensor()
@@ -145,11 +102,11 @@
 }
 
 status_t GyroDriftSensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(FUSION_9AXIS, ident, enabled);
+    return mSensorFusion.activate(ident, enabled);
 }
 
 status_t GyroDriftSensor::setDelay(void* ident, int /*handle*/, int64_t ns) {
-    return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
+    return mSensorFusion.setDelay(ident, ns);
 }
 
 Sensor GyroDriftSensor::getSensor() const {
diff --git a/services/sensorservice/RotationVectorSensor.h b/services/sensorservice/RotationVectorSensor.h
index 1fc316b..bb97fe1 100644
--- a/services/sensorservice/RotationVectorSensor.h
+++ b/services/sensorservice/RotationVectorSensor.h
@@ -35,14 +35,9 @@
 class RotationVectorSensor : public SensorInterface {
     SensorDevice& mSensorDevice;
     SensorFusion& mSensorFusion;
-    int mMode;
-
-    int getSensorType() const;
-    const char* getSensorName() const ;
-    int getSensorToken() const ;
 
 public:
-    RotationVectorSensor(int mode = FUSION_9AXIS);
+    RotationVectorSensor();
     virtual bool process(sensors_event_t* outEvent,
             const sensors_event_t& event);
     virtual status_t activate(void* ident, bool enabled);
@@ -51,16 +46,6 @@
     virtual bool isVirtual() const { return true; }
 };
 
-class GameRotationVectorSensor : public RotationVectorSensor {
-public:
-    GameRotationVectorSensor() : RotationVectorSensor(FUSION_NOMAG) {}
-};
-
-class GeoMagRotationVectorSensor : public RotationVectorSensor {
-public:
-    GeoMagRotationVectorSensor() : RotationVectorSensor(FUSION_NOGYRO) {}
-};
-
 class GyroDriftSensor : public SensorInterface {
     SensorDevice& mSensorDevice;
     SensorFusion& mSensorFusion;
diff --git a/services/sensorservice/SensorFusion.cpp b/services/sensorservice/SensorFusion.cpp
index 9863f62..6d93009 100644
--- a/services/sensorservice/SensorFusion.cpp
+++ b/services/sensorservice/SensorFusion.cpp
@@ -25,17 +25,11 @@
 
 SensorFusion::SensorFusion()
     : mSensorDevice(SensorDevice::getInstance()),
-      mAttitude(mAttitudes[FUSION_9AXIS]),
-      mGyroTime(0), mAccTime(0)
+      mEnabled(false), mGyroTime(0)
 {
     sensor_t const* list;
     Sensor uncalibratedGyro;
     ssize_t count = mSensorDevice.getSensorList(&list);
-
-    mEnabled[FUSION_9AXIS] = false;
-    mEnabled[FUSION_NOMAG] = false;
-    mEnabled[FUSION_NOGYRO] = false;
-
     if (count > 0) {
         for (size_t i=0 ; i<size_t(count) ; i++) {
             if (list[i].type == SENSOR_TYPE_ACCELEROMETER) {
@@ -61,121 +55,81 @@
         // and power/cpu usage.
         mEstimatedGyroRate = 200;
         mTargetDelayNs = 1000000000LL/mEstimatedGyroRate;
-
-        for (int i = 0; i<NUM_FUSION_MODE; ++i) {
-            mFusions[i].init(i);
-        }
+        mFusion.init();
     }
 }
 
 void SensorFusion::process(const sensors_event_t& event) {
-
     if (event.type == mGyro.getType()) {
-        float dT;
-        if ( event.timestamp - mGyroTime> 0 &&
-             event.timestamp - mGyroTime< (int64_t)(5e7) ) { //0.05sec
-
-            dT = (event.timestamp - mGyroTime) / 1000000000.0f;
+        if (mGyroTime != 0) {
+            const float dT = (event.timestamp - mGyroTime) / 1000000000.0f;
+            mFusion.handleGyro(vec3_t(event.data), dT);
             // here we estimate the gyro rate (useful for debugging)
             const float freq = 1 / dT;
             if (freq >= 100 && freq<1000) { // filter values obviously wrong
                 const float alpha = 1 / (1 + dT); // 1s time-constant
                 mEstimatedGyroRate = freq + (mEstimatedGyroRate - freq)*alpha;
             }
-
-            const vec3_t gyro(event.data);
-            for (int i = 0; i<NUM_FUSION_MODE; ++i) {
-                if (mEnabled[i]) {
-                    // fusion in no gyro mode will ignore
-                    mFusions[i].handleGyro(gyro, dT);
-                }
-            }
         }
         mGyroTime = event.timestamp;
     } else if (event.type == SENSOR_TYPE_MAGNETIC_FIELD) {
         const vec3_t mag(event.data);
-        for (int i = 0; i<NUM_FUSION_MODE; ++i) {
-            if (mEnabled[i]) {
-                mFusions[i].handleMag(mag);// fusion in no mag mode will ignore
-            }
-        }
+        mFusion.handleMag(mag);
     } else if (event.type == SENSOR_TYPE_ACCELEROMETER) {
-        float dT;
-        if ( event.timestamp - mAccTime> 0 &&
-             event.timestamp - mAccTime< (int64_t)(1e8) ) { //0.1sec
-            dT = (event.timestamp - mAccTime) / 1000000000.0f;
-
-            const vec3_t acc(event.data);
-            for (int i = 0; i<NUM_FUSION_MODE; ++i) {
-                if (mEnabled[i]) {
-                    mFusions[i].handleAcc(acc, dT);
-                    mAttitudes[i] = mFusions[i].getAttitude();
-                }
-            }
-        }
-        mAccTime = event.timestamp;
+        const vec3_t acc(event.data);
+        mFusion.handleAcc(acc);
+        mAttitude = mFusion.getAttitude();
     }
 }
 
 template <typename T> inline T min(T a, T b) { return a<b ? a : b; }
 template <typename T> inline T max(T a, T b) { return a>b ? a : b; }
 
-status_t SensorFusion::activate(int mode, void* ident, bool enabled) {
+status_t SensorFusion::activate(void* ident, bool enabled) {
 
     ALOGD_IF(DEBUG_CONNECTIONS,
-            "SensorFusion::activate(mode=%d, ident=%p, enabled=%d)",
-            mode, ident, enabled);
+            "SensorFusion::activate(ident=%p, enabled=%d)",
+            ident, enabled);
 
-    const ssize_t idx = mClients[mode].indexOf(ident);
+    const ssize_t idx = mClients.indexOf(ident);
     if (enabled) {
         if (idx < 0) {
-            mClients[mode].add(ident);
+            mClients.add(ident);
         }
     } else {
         if (idx >= 0) {
-            mClients[mode].removeItemsAt(idx);
-        }
-    }
-
-    const bool newState = mClients[mode].size() != 0;
-    if (newState != mEnabled[mode]) {
-        mEnabled[mode] = newState;
-        if (newState) {
-            mFusions[mode].init(mode);
+            mClients.removeItemsAt(idx);
         }
     }
 
     mSensorDevice.activate(ident, mAcc.getHandle(), enabled);
-    if (mode != FUSION_NOMAG) {
-        mSensorDevice.activate(ident, mMag.getHandle(), enabled);
-    }
-    if (mode != FUSION_NOGYRO) {
-        mSensorDevice.activate(ident, mGyro.getHandle(), enabled);
-    }
+    mSensorDevice.activate(ident, mMag.getHandle(), enabled);
+    mSensorDevice.activate(ident, mGyro.getHandle(), enabled);
 
+    const bool newState = mClients.size() != 0;
+    if (newState != mEnabled) {
+        mEnabled = newState;
+        if (newState) {
+            mFusion.init();
+            mGyroTime = 0;
+        }
+    }
     return NO_ERROR;
 }
 
-status_t SensorFusion::setDelay(int mode, void* ident, int64_t ns) {
+status_t SensorFusion::setDelay(void* ident, int64_t ns) {
     // Call batch with timeout zero instead of setDelay().
-    if (ns > (int64_t)5e7) {
-        ns = (int64_t)(5e7);
-    }
     mSensorDevice.batch(ident, mAcc.getHandle(), 0, ns, 0);
-    if (mode != FUSION_NOMAG) {
-        mSensorDevice.batch(ident, mMag.getHandle(), 0, ms2ns(20), 0);
-    }
-    if (mode != FUSION_NOGYRO) {
-        mSensorDevice.batch(ident, mGyro.getHandle(), 0, mTargetDelayNs, 0);
-    }
+    mSensorDevice.batch(ident, mMag.getHandle(), 0, ms2ns(20), 0);
+    mSensorDevice.batch(ident, mGyro.getHandle(), 0, mTargetDelayNs, 0);
     return NO_ERROR;
 }
 
 
-float SensorFusion::getPowerUsage(int mode) const {
+float SensorFusion::getPowerUsage() const {
     float power =   mAcc.getPowerUsage() +
-                    ((mode != FUSION_NOMAG) ? mMag.getPowerUsage() : 0) +
-                    ((mode != FUSION_NOGYRO) ? mGyro.getPowerUsage() : 0);
+                    mMag.getPowerUsage() +
+                    mGyro.getPowerUsage();
     return power;
 }
 
@@ -184,55 +138,21 @@
 }
 
 void SensorFusion::dump(String8& result) {
-    const Fusion& fusion_9axis(mFusions[FUSION_9AXIS]);
+    const Fusion& fusion(mFusion);
     result.appendFormat("9-axis fusion %s (%zd clients), gyro-rate=%7.2fHz, "
             "q=< %g, %g, %g, %g > (%g), "
             "b=< %g, %g, %g >\n",
-            mEnabled[FUSION_9AXIS] ? "enabled" : "disabled",
-            mClients[FUSION_9AXIS].size(),
+            mEnabled ? "enabled" : "disabled",
+            mClients.size(),
             mEstimatedGyroRate,
-            fusion_9axis.getAttitude().x,
-            fusion_9axis.getAttitude().y,
-            fusion_9axis.getAttitude().z,
-            fusion_9axis.getAttitude().w,
-            length(fusion_9axis.getAttitude()),
-            fusion_9axis.getBias().x,
-            fusion_9axis.getBias().y,
-            fusion_9axis.getBias().z);
-
-    const Fusion& fusion_nomag(mFusions[FUSION_NOMAG]);
-    result.appendFormat("game fusion(no mag) %s (%zd clients), "
-            "gyro-rate=%7.2fHz, "
-            "q=< %g, %g, %g, %g > (%g), "
-            "b=< %g, %g, %g >\n",
-            mEnabled[FUSION_NOMAG] ? "enabled" : "disabled",
-            mClients[FUSION_NOMAG].size(),
-            mEstimatedGyroRate,
-            fusion_nomag.getAttitude().x,
-            fusion_nomag.getAttitude().y,
-            fusion_nomag.getAttitude().z,
-            fusion_nomag.getAttitude().w,
-            length(fusion_nomag.getAttitude()),
-            fusion_nomag.getBias().x,
-            fusion_nomag.getBias().y,
-            fusion_nomag.getBias().z);
-
-    const Fusion& fusion_nogyro(mFusions[FUSION_NOGYRO]);
-    result.appendFormat("geomag fusion (no gyro) %s (%zd clients), "
-            "gyro-rate=%7.2fHz, "
-            "q=< %g, %g, %g, %g > (%g), "
-            "b=< %g, %g, %g >\n",
-            mEnabled[FUSION_NOGYRO] ? "enabled" : "disabled",
-            mClients[FUSION_NOGYRO].size(),
-            mEstimatedGyroRate,
-            fusion_nogyro.getAttitude().x,
-            fusion_nogyro.getAttitude().y,
-            fusion_nogyro.getAttitude().z,
-            fusion_nogyro.getAttitude().w,
-            length(fusion_nogyro.getAttitude()),
-            fusion_nogyro.getBias().x,
-            fusion_nogyro.getBias().y,
-            fusion_nogyro.getBias().z);
+            fusion.getAttitude().x,
+            fusion.getAttitude().y,
+            fusion.getAttitude().z,
+            fusion.getAttitude().w,
+            length(fusion.getAttitude()),
+            fusion.getBias().x,
+            fusion.getBias().y,
+            fusion.getBias().z);
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/SensorFusion.h b/services/sensorservice/SensorFusion.h
index ad636d5..432adbc 100644
--- a/services/sensorservice/SensorFusion.h
+++ b/services/sensorservice/SensorFusion.h
@@ -42,52 +42,30 @@
     Sensor mAcc;
     Sensor mMag;
     Sensor mGyro;
-
-    Fusion mFusions[NUM_FUSION_MODE]; // normal, no_mag, no_gyro
-
-    bool mEnabled[NUM_FUSION_MODE];
-
-    vec4_t &mAttitude;
-    vec4_t mAttitudes[NUM_FUSION_MODE];
-
-    SortedVector<void*> mClients[3];
-
+    Fusion mFusion;
+    bool mEnabled;
     float mEstimatedGyroRate;
     nsecs_t mTargetDelayNs;
-
     nsecs_t mGyroTime;
-    nsecs_t mAccTime;
+    vec4_t mAttitude;
+    SortedVector<void*> mClients;
 
     SensorFusion();
 
 public:
     void process(const sensors_event_t& event);
 
-    bool isEnabled() const {
-        return mEnabled[FUSION_9AXIS] ||
-                mEnabled[FUSION_NOMAG] ||
-                mEnabled[FUSION_NOGYRO];
-    }
-
-    bool hasEstimate(int mode = FUSION_9AXIS) const {
-        return mFusions[mode].hasEstimate();
-    }
-
-    mat33_t getRotationMatrix(int mode = FUSION_9AXIS) const {
-        return mFusions[mode].getRotationMatrix();
-    }
-
-    vec4_t getAttitude(int mode = FUSION_9AXIS) const {
-        return mAttitudes[mode];
-    }
-
-    vec3_t getGyroBias() const { return mFusions[FUSION_9AXIS].getBias(); }
+    bool isEnabled() const { return mEnabled; }
+    bool hasEstimate() const { return mFusion.hasEstimate(); }
+    mat33_t getRotationMatrix() const { return mFusion.getRotationMatrix(); }
+    vec4_t getAttitude() const { return mAttitude; }
+    vec3_t getGyroBias() const { return mFusion.getBias(); }
     float getEstimatedRate() const { return mEstimatedGyroRate; }
 
-    status_t activate(int mode, void* ident, bool enabled);
-    status_t setDelay(int mode, void* ident, int64_t ns);
+    status_t activate(void* ident, bool enabled);
+    status_t setDelay(void* ident, int64_t ns);
 
-    float getPowerUsage(int mode=FUSION_9AXIS) const;
+    float getPowerUsage() const;
     int32_t getMinDelay() const;
 
     void dump(String8& result);
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
old mode 100755
new mode 100644
index c73af3a..2f64558
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -88,14 +88,11 @@
             uint32_t virtualSensorsNeeds =
                     (1<<SENSOR_TYPE_GRAVITY) |
                     (1<<SENSOR_TYPE_LINEAR_ACCELERATION) |
-                    (1<<SENSOR_TYPE_ROTATION_VECTOR) |
-                    (1<<SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR) |
-                    (1<<SENSOR_TYPE_GAME_ROTATION_VECTOR);
+                    (1<<SENSOR_TYPE_ROTATION_VECTOR);
 
             mLastEventSeen.setCapacity(count);
             for (ssize_t i=0 ; i<count ; i++) {
-                bool useThisSensor=true;
-
+                registerSensor( new HardwareSensor(list[i]) );
                 switch (list[i].type) {
                     case SENSOR_TYPE_ACCELEROMETER:
                         hasAccel = true;
@@ -113,18 +110,9 @@
                     case SENSOR_TYPE_GRAVITY:
                     case SENSOR_TYPE_LINEAR_ACCELERATION:
                     case SENSOR_TYPE_ROTATION_VECTOR:
-                    case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
-                    case SENSOR_TYPE_GAME_ROTATION_VECTOR:
-                        if (IGNORE_HARDWARE_FUSION) {
-                            useThisSensor = false;
-                        } else {
-                            virtualSensorsNeeds &= ~(1<<list[i].type);
-                        }
+                        virtualSensorsNeeds &= ~(1<<list[i].type);
                         break;
                 }
-                if (useThisSensor) {
-                    registerSensor( new HardwareSensor(list[i]) );
-                }
             }
 
             // it's safe to instantiate the SensorFusion object here
@@ -136,15 +124,26 @@
             mUserSensorList = mSensorList;
 
             if (hasGyro && hasAccel && hasMag) {
+                Sensor aSensor;
+
                 // Add Android virtual sensors if they're not already
                 // available in the HAL
-                Sensor aSensor;
 
                 aSensor = registerVirtualSensor( new RotationVectorSensor() );
                 if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
                     mUserSensorList.add(aSensor);
                 }
 
+                aSensor = registerVirtualSensor( new GravitySensor(list, count) );
+                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) {
+                    mUserSensorList.add(aSensor);
+                }
+
+                aSensor = registerVirtualSensor( new LinearAccelerationSensor(list, count) );
+                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) {
+                    mUserSensorList.add(aSensor);
+                }
+
                 aSensor = registerVirtualSensor( new OrientationSensor() );
                 if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
                     // if we are doing our own rotation-vector, also add
@@ -152,46 +151,11 @@
                     mUserSensorList.replaceAt(aSensor, orientationIndex);
                 }
 
-                aSensor = registerVirtualSensor(
-                                new LinearAccelerationSensor(list, count) );
-                if (virtualSensorsNeeds &
-                            (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) {
-                    mUserSensorList.add(aSensor);
-                }
-
                 // virtual debugging sensors are not added to mUserSensorList
                 registerVirtualSensor( new CorrectedGyroSensor(list, count) );
                 registerVirtualSensor( new GyroDriftSensor() );
             }
 
-            if (hasAccel && hasGyro) {
-                Sensor aSensor;
-
-                aSensor = registerVirtualSensor(
-                                new GravitySensor(list, count) );
-                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) {
-                    mUserSensorList.add(aSensor);
-                }
-
-                aSensor = registerVirtualSensor(
-                                new GameRotationVectorSensor() );
-                if (virtualSensorsNeeds &
-                            (1<<SENSOR_TYPE_GAME_ROTATION_VECTOR)) {
-                    mUserSensorList.add(aSensor);
-                }
-            }
-
-            if (hasAccel && hasMag) {
-                Sensor aSensor;
-
-                aSensor = registerVirtualSensor(
-                                new GeoMagRotationVectorSensor() );
-                if (virtualSensorsNeeds &
-                        (1<<SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR)) {
-                    mUserSensorList.add(aSensor);
-                }
-            }
-
             // debugging sensor list
             mUserSensorListDebug = mSensorList;
 
@@ -759,7 +723,14 @@
     Vector<Sensor> accessibleSensorList;
     for (size_t i = 0; i < initialSensorList.size(); i++) {
         Sensor sensor = initialSensorList[i];
-        accessibleSensorList.add(sensor);
+        if (canAccessSensor(sensor, "getSensorList", opPackageName)) {
+            accessibleSensorList.add(sensor);
+        } else {
+            ALOGI("Skipped sensor %s because it requires permission %s and app op %d",
+                  sensor.getName().string(),
+                  sensor.getRequiredPermission().string(),
+                  sensor.getRequiredAppOp());
+        }
     }
     return accessibleSensorList;
 }
@@ -1655,26 +1626,21 @@
                 reAllocateCacheLocked(scratch, count);
                 return status_t(NO_ERROR);
             }
-            if (count >= mMaxCacheSize) {
-                //count is larger than MaxCacheSize,
-                //so copy the end MaxCacheSize data in scratch buffer to cache
-                countFlushCompleteEventsLocked(mEventCache, mCacheSize);
-                countFlushCompleteEventsLocked(scratch, count - mMaxCacheSize);
-                memcpy(&mEventCache[0], &scratch[count-mMaxCacheSize],
-                    mMaxCacheSize * sizeof(sensors_event_t));
-                mCacheSize = mMaxCacheSize;
-            } else {
-                //count is smaller than MaxCacheSize, so numEventsDropped data in cache
-                //should be dropped, then copy the scratch to the end of cache
-                int numEventsDropped = count + mCacheSize - mMaxCacheSize;
-                countFlushCompleteEventsLocked(mEventCache, numEventsDropped);
-                memmove(mEventCache, &mEventCache[numEventsDropped],
+            // Some events need to be dropped.
+            int remaningCacheSize = mMaxCacheSize - mCacheSize;
+            if (remaningCacheSize != 0) {
+                memcpy(&mEventCache[mCacheSize], scratch,
+                                                remaningCacheSize * sizeof(sensors_event_t));
+            }
+            int numEventsDropped = count - remaningCacheSize;
+            countFlushCompleteEventsLocked(mEventCache, numEventsDropped);
+            // Drop the first "numEventsDropped" in the cache.
+            memmove(mEventCache, &mEventCache[numEventsDropped],
                     (mCacheSize - numEventsDropped) * sizeof(sensors_event_t));
 
-                memcpy(&mEventCache[mCacheSize - numEventsDropped], scratch,
-                    count * sizeof(sensors_event_t));
-                mCacheSize = mMaxCacheSize;
-            }
+            // Copy the remainingEvents in scratch buffer to the end of cache.
+            memcpy(&mEventCache[mCacheSize - numEventsDropped], scratch + remaningCacheSize,
+                                            numEventsDropped * sizeof(sensors_event_t));
         }
         return status_t(NO_ERROR);
     }
@@ -1693,7 +1659,6 @@
                                     reinterpret_cast<ASensorEvent const*>(scratch), count);
     if (size < 0) {
         // Write error, copy events to local cache.
-        ALOGE("write failed, size=%d  err=%d:%s ", size, errno, strerror(errno));
         if (index_wake_up_event >= 0) {
             // If there was a wake_up sensor_event, reset the flag.
             scratch[index_wake_up_event].flags &= ~WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
@@ -1709,21 +1674,8 @@
             mEventCache = new sensors_event_t[mMaxCacheSize];
             mCacheSize = 0;
         }
-        //here mCacheSize must be 0 because if (mCacheSize != 0) has been executed above
-        if (count <= mMaxCacheSize) {
-            //count is no more than free size of cache,
-            //copy the scratch to the end of cache
-            memcpy(&mEventCache[0], scratch, count * sizeof(sensors_event_t));
-            mCacheSize = count;
-        } else {
-            //count is larger than free size of cache,
-            //so just copy the free size of scratch to the end of cache
-            ALOGI("count > MaxCache count=%d mMaxCacheSize=%d", count, mMaxCacheSize);
-            countFlushCompleteEventsLocked(scratch, count - mMaxCacheSize);
-            memcpy(&mEventCache[0], &scratch[count - mMaxCacheSize],
-                mMaxCacheSize * sizeof(sensors_event_t));
-            mCacheSize = mMaxCacheSize;
-        }
+        memcpy(&mEventCache[mCacheSize], scratch, count * sizeof(sensors_event_t));
+        mCacheSize += count;
 
         // Add this file descriptor to the looper to get a callback when this fd is available for
         // writing.
@@ -1776,7 +1728,6 @@
             }
             ssize_t size = SensorEventQueue::write(mChannel, &flushCompleteEvent, 1);
             if (size < 0) {
-                ALOGE("write failed, size=%d  err=%d:%s ", size, errno, strerror(errno));
                 if (wakeUpSensor) --mWakeLockRefCount;
                 return;
             }
@@ -1812,7 +1763,6 @@
                           reinterpret_cast<ASensorEvent const*>(mEventCache + numEventsSent),
                           numEventsToWrite);
         if (size < 0) {
-            ALOGE("write failed, size=%d  err=%d:%s ", size, errno, strerror(errno));
             if (index_wake_up_event >= 0) {
                 // If there was a wake_up sensor_event, reset the flag.
                 mEventCache[index_wake_up_event + numEventsSent].flags  &=
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 7d81d6e..9a573ae 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -46,7 +46,7 @@
 #endif
 
 // ---------------------------------------------------------------------------
-#define IGNORE_HARDWARE_FUSION  false
+
 #define DEBUG_CONNECTIONS   false
 // Max size is 100 KB which is enough to accept a batch of about 1000 events.
 #define MAX_SOCKET_BUFFER_SIZE_BATCHED 100 * 1024
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 1eb2361..1901ef9 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -122,6 +122,10 @@
 LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
 LOCAL_CPPFLAGS := -std=c++11
 
+ifneq ($(ENABLE_CPUSETS),)
+    LOCAL_CFLAGS += -DENABLE_CPUSETS
+endif
+
 LOCAL_SRC_FILES := \
     main_surfaceflinger.cpp
 
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index a74bc4c..6fa8b53 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -41,6 +41,13 @@
 
     set_sched_policy(0, SP_FOREGROUND);
 
+#ifdef ENABLE_CPUSETS
+    // Put most SurfaceFlinger threads in the system-background cpuset
+    // Keeps us from unnecessarily using big cores
+    // Do this after the binder thread pool init
+    set_cpuset_policy(0, SP_SYSTEM);
+#endif
+
     // initialize before clients can connect
     flinger->init();