[DO NOT MERGE ANYWHERE] Fix bodysensor permission

Bug: 26481493
Bug: 26447970

Change-Id: Iaadf64814c03ae8098c8553ac98d19b77c1eabcd
diff --git a/include/gui/SensorManager.h b/include/gui/SensorManager.h
index 0cff46c..f039caf 100644
--- a/include/gui/SensorManager.h
+++ b/include/gui/SensorManager.h
@@ -22,9 +22,11 @@
 #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>
@@ -54,7 +56,8 @@
     static SensorManager& getInstanceForPackage(const String16& packageName);
     ~SensorManager();
 
-    ssize_t getSensorList(Sensor const* const** list) const;
+    ssize_t getSensorList(Sensor const* const** list);
+    ssize_t getAvailableSensorList(Sensor const* const** list);
     Sensor const* getDefaultSensor(int type);
     sp<SensorEventQueue> createEventQueue(String8 packageName = String8(""), int mode = 0);
     bool isDataInjectionEnabled();
@@ -64,18 +67,27 @@
     void sensorManagerDied();
 
     SensorManager(const String16& opPackageName);
-    status_t assertStateLocked() const;
+    status_t assertStateLocked();
+    void updateAvailableSensorList();
 
 private:
     static Mutex sLock;
     static std::map<String16, SensorManager*> sPackageInstances;
 
-    mutable Mutex mLock;
-    mutable sp<ISensorServer> mSensorServer;
-    mutable Sensor const** mSensorList;
-    mutable Vector<Sensor> mSensors;
-    mutable sp<IBinder::DeathRecipient> mDeathObserver;
+    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;
     const String16 mOpPackageName;
+    bool mBodyPermission;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp
index 33608b5..4277032 100644
--- a/libs/gui/SensorManager.cpp
+++ b/libs/gui/SensorManager.cpp
@@ -89,7 +89,8 @@
 }
 
 SensorManager::SensorManager(const String16& opPackageName)
-    : mSensorList(0), mOpPackageName(opPackageName)
+    : mSensorList(NULL), mAvailableSensorList(NULL), mNumAvailableSensor(0),
+      mOpPackageName(opPackageName), mBodyPermission(false)
 {
     // okay we're not locked here, but it's not needed during construction
     assertStateLocked();
@@ -98,6 +99,9 @@
 SensorManager::~SensorManager()
 {
     free(mSensorList);
+    if (mAvailableSensorList) {
+        free(mAvailableSensorList);
+    }
 }
 
 void SensorManager::sensorManagerDied()
@@ -106,10 +110,14 @@
     mSensorServer.clear();
     free(mSensorList);
     mSensorList = NULL;
+    if (mAvailableSensorList) {
+        free(mAvailableSensorList);
+        mAvailableSensorList = NULL;
+    }
     mSensors.clear();
 }
 
-status_t SensorManager::assertStateLocked() const {
+status_t SensorManager::assertStateLocked() {
     bool initSensorManager = false;
     if (mSensorServer == NULL) {
         initSensorManager = true;
@@ -159,13 +167,14 @@
         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) const
-{
+ssize_t SensorManager::getSensorList(Sensor const* const** list) {
     Mutex::Autolock _l(mLock);
     status_t err = assertStateLocked();
     if (err < 0) {
@@ -175,10 +184,76 @@
     return static_cast<ssize_t>(mSensors.size());
 }
 
-Sensor const* SensorManager::getDefaultSensor(int type)
-{
+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) {
     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
@@ -192,9 +267,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 (mSensorList[i]->getType() == type &&
-                mSensorList[i]->isWakeUpSensor() == wakeUpSensor) {
-                return mSensorList[i];
+            if (mAvailableSensorList[i]->getType() == type &&
+                mAvailableSensorList[i]->isWakeUpSensor() == wakeUpSensor) {
+                return mAvailableSensorList[i];
             }
         }
     }
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index fd72b23..956d8e8 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -723,14 +723,7 @@
     Vector<Sensor> accessibleSensorList;
     for (size_t i = 0; i < initialSensorList.size(); i++) {
         Sensor sensor = initialSensorList[i];
-        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());
-        }
+        accessibleSensorList.add(sensor);
     }
     return accessibleSensorList;
 }