Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1000b336 authored by Arthur Ishiguro's avatar Arthur Ishiguro Committed by Automerger Merge Worker
Browse files

Disable sensors when an app goes to background v2 am: 539c27c9

Change-Id: I00eb420452ca46af0c2632fa47a9e3019381e0ad
parents 53882cc1 539c27c9
Loading
Loading
Loading
Loading
+96 −29
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@
#include "android/hardware/sensors/2.1/ISensorsCallback.h"
#include "android/hardware/sensors/2.1/types.h"
#include "convertV2_1.h"
#include "SensorService.h"

#include <android-base/logging.h>
#include <android/util/ProtoOutputStream.h>
@@ -30,6 +29,7 @@
#include <utils/Errors.h>
#include <utils/Singleton.h>

#include <cstddef>
#include <chrono>
#include <cinttypes>
#include <thread>
@@ -403,8 +403,8 @@ std::string SensorDevice::dump() const {
    if (mSensors == nullptr) return "HAL not initialized\n";

    String8 result;
    result.appendFormat("Total %zu h/w sensors, %zu running:\n",
                        mSensorList.size(), mActivationCount.size());
    result.appendFormat("Total %zu h/w sensors, %zu running %zu disabled clients:\n",
                        mSensorList.size(), mActivationCount.size(), mDisabledClients.size());

    Mutex::Autolock _l(mLock);
    for (const auto & s : mSensorList) {
@@ -417,16 +417,18 @@ std::string SensorDevice::dump() const {
        result.append("sampling_period(ms) = {");
        for (size_t j = 0; j < info.batchParams.size(); j++) {
            const BatchParams& params = info.batchParams[j];
            result.appendFormat("%.1f%s", params.mTSample / 1e6f,
                j < info.batchParams.size() - 1 ? ", " : "");
            result.appendFormat("%.1f%s%s", params.mTSample / 1e6f,
                isClientDisabledLocked(info.batchParams.keyAt(j)) ? "(disabled)" : "",
                (j < info.batchParams.size() - 1) ? ", " : "");
        }
        result.appendFormat("}, selected = %.2f ms; ", info.bestBatchParams.mTSample / 1e6f);

        result.append("batching_period(ms) = {");
        for (size_t j = 0; j < info.batchParams.size(); j++) {
            const BatchParams& params = info.batchParams[j];
            result.appendFormat("%.1f%s", params.mTBatch / 1e6f,
                    j < info.batchParams.size() - 1 ? ", " : "");
            result.appendFormat("%.1f%s%s", params.mTBatch / 1e6f,
                    isClientDisabledLocked(info.batchParams.keyAt(j)) ? "(disabled)" : "",
                    (j < info.batchParams.size() - 1) ? ", " : "");
        }
        result.appendFormat("}, selected = %.2f ms\n", info.bestBatchParams.mTBatch / 1e6f);
    }
@@ -641,7 +643,7 @@ status_t SensorDevice::activate(void* ident, int handle, int enabled) {
}

status_t SensorDevice::activateLocked(void* ident, int handle, int enabled) {
    bool actuateHardware = false;
    bool activateHardware = false;

    status_t err(NO_ERROR);

@@ -667,7 +669,7 @@ status_t SensorDevice::activateLocked(void* ident, int handle, int enabled) {

        if (info.batchParams.indexOfKey(ident) >= 0) {
            if (info.numActiveClients() > 0 && !info.isActive) {
                actuateHardware = true;
                activateHardware = true;
            }
        } else {
            // Log error. Every activate call should be preceded by a batch() call.
@@ -687,7 +689,7 @@ status_t SensorDevice::activateLocked(void* ident, int handle, int enabled) {
        if (info.removeBatchParamsForIdent(ident) >= 0) {
            if (info.numActiveClients() == 0) {
                // This is the last connection, we need to de-activate the underlying h/w sensor.
                actuateHardware = true;
                activateHardware = true;
            } else {
                // Call batch for this sensor with the previously calculated best effort
                // batch_rate and timeout. One of the apps has unregistered for sensor
@@ -707,12 +709,8 @@ status_t SensorDevice::activateLocked(void* ident, int handle, int enabled) {
        }
    }

    if (actuateHardware) {
        ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
                 enabled);
        err = checkReturnAndGetStatus(mSensors->activate(handle, enabled));
        ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
                 strerror(-err));
    if (activateHardware) {
        err = doActivateHardwareLocked(handle, enabled);

        if (err != NO_ERROR && enabled) {
            // Failure when enabling the sensor. Clean up on failure.
@@ -728,6 +726,15 @@ status_t SensorDevice::activateLocked(void* ident, int handle, int enabled) {
    return err;
}

status_t SensorDevice::doActivateHardwareLocked(int handle, bool enabled) {
    ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
             enabled);
    status_t err = checkReturnAndGetStatus(mSensors->activate(handle, enabled));
    ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
             strerror(-err));
    return err;
}

status_t SensorDevice::batch(
        void* ident,
        int handle,
@@ -768,6 +775,18 @@ status_t SensorDevice::batchLocked(void* ident, int handle, int flags, int64_t s
        info.setBatchParamsForIdent(ident, flags, samplingPeriodNs, maxBatchReportLatencyNs);
    }

    status_t err =  updateBatchParamsLocked(handle, info);
    if (err != NO_ERROR) {
        ALOGE("sensor batch failed %p 0x%08x %" PRId64 " %" PRId64 " err=%s",
              mSensors.get(), handle, info.bestBatchParams.mTSample,
              info.bestBatchParams.mTBatch, strerror(-err));
        info.removeBatchParamsForIdent(ident);
    }

    return err;
}

status_t SensorDevice::updateBatchParamsLocked(int handle, Info &info) {
    BatchParams prevBestBatchParams = info.bestBatchParams;
    // Find the minimum of all timeouts and batch_rates for this sensor.
    info.selectBatchParams();
@@ -785,13 +804,8 @@ status_t SensorDevice::batchLocked(void* ident, int handle, int flags, int64_t s
                 info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch);
        err = checkReturnAndGetStatus(mSensors->batch(
                handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch));
        if (err != NO_ERROR) {
            ALOGE("sensor batch failed %p 0x%08x %" PRId64 " %" PRId64 " err=%s",
                  mSensors.get(), handle, info.bestBatchParams.mTSample,
                  info.bestBatchParams.mTBatch, strerror(-err));
            info.removeBatchParamsForIdent(ident);
        }
    }

    return err;
}

@@ -811,13 +825,61 @@ status_t SensorDevice::flush(void* ident, int handle) {
    return checkReturnAndGetStatus(mSensors->flush(handle));
}

bool SensorDevice::isClientDisabled(void* ident) {
bool SensorDevice::isClientDisabled(void* ident) const {
    Mutex::Autolock _l(mLock);
    return isClientDisabledLocked(ident);
}

bool SensorDevice::isClientDisabledLocked(void* ident) {
    return mDisabledClients.indexOf(ident) >= 0;
bool SensorDevice::isClientDisabledLocked(void* ident) const {
    return mDisabledClients.count(ident) > 0;
}

std::vector<void *> SensorDevice::getDisabledClientsLocked() const {
    std::vector<void *> vec;
    for (const auto& it : mDisabledClients) {
        vec.push_back(it.first);
    }

    return vec;
}

void SensorDevice::addDisabledReasonForIdentLocked(void* ident, DisabledReason reason) {
    mDisabledClients[ident] |= 1 << reason;
}

void SensorDevice::removeDisabledReasonForIdentLocked(void* ident, DisabledReason reason) {
    if (isClientDisabledLocked(ident)) {
        mDisabledClients[ident] &= ~(1 << reason);
        if (mDisabledClients[ident] == 0) {
            mDisabledClients.erase(ident);
        }
    }
}

void SensorDevice::setUidStateForConnection(void* ident, SensorService::UidState state) {
    Mutex::Autolock _l(mLock);
    if (state == SensorService::UID_STATE_ACTIVE) {
        removeDisabledReasonForIdentLocked(ident, DisabledReason::DISABLED_REASON_UID_IDLE);
    } else {
        addDisabledReasonForIdentLocked(ident, DisabledReason::DISABLED_REASON_UID_IDLE);
    }

    for (size_t i = 0; i< mActivationCount.size(); ++i) {
        int handle = mActivationCount.keyAt(i);
        Info& info = mActivationCount.editValueAt(i);

        if (info.hasBatchParamsForIdent(ident)) {
            if (updateBatchParamsLocked(handle, info) != NO_ERROR) {
                bool enable = info.numActiveClients() == 0 && info.isActive;
                bool disable = info.numActiveClients() > 0 && !info.isActive;

                if ((enable || disable) &&
                    doActivateHardwareLocked(handle, enable) == NO_ERROR) {
                    info.isActive = enable;
                }
            }
        }
    }
}

bool SensorDevice::isSensorActive(int handle) const {
@@ -832,8 +894,12 @@ bool SensorDevice::isSensorActive(int handle) const {
void SensorDevice::enableAllSensors() {
    if (mSensors == nullptr) return;
    Mutex::Autolock _l(mLock);
    mDisabledClients.clear();
    ALOGI("cleared mDisabledClients");

    for (void *client : getDisabledClientsLocked()) {
        removeDisabledReasonForIdentLocked(
            client, DisabledReason::DISABLED_REASON_SERVICE_RESTRICTED);
    }

    for (size_t i = 0; i< mActivationCount.size(); ++i) {
        Info& info = mActivationCount.editValueAt(i);
        if (info.batchParams.isEmpty()) continue;
@@ -873,7 +939,8 @@ void SensorDevice::disableAllSensors() {
           // Add all the connections that were registered for this sensor to the disabled
           // clients list.
           for (size_t j = 0; j < info.batchParams.size(); ++j) {
               mDisabledClients.add(info.batchParams.keyAt(j));
               addDisabledReasonForIdentLocked(
                   info.batchParams.keyAt(j), DisabledReason::DISABLED_REASON_SERVICE_RESTRICTED);
               ALOGI("added %p to mDisabledClients", info.batchParams.keyAt(j));
           }

@@ -1048,7 +1115,7 @@ ssize_t SensorDevice::Info::removeBatchParamsForIdent(void* ident) {

void SensorDevice::notifyConnectionDestroyed(void* ident) {
    Mutex::Autolock _l(mLock);
    mDisabledClients.remove(ident);
    mDisabledClients.erase(ident);
}

bool SensorDevice::isDirectReportSupported() const {
+38 −4
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#define ANDROID_SENSOR_DEVICE_H

#include "SensorDeviceUtils.h"
#include "SensorService.h"
#include "SensorServiceUtils.h"
#include "ISensorsWrapper.h"

@@ -116,6 +117,8 @@ public:
    hardware::Return<void> onDynamicSensorsDisconnected(
            const hardware::hidl_vec<int32_t> &dynamicSensorHandlesRemoved);

    void setUidStateForConnection(void* ident, SensorService::UidState state);

    bool isReconnecting() const {
        return mReconnecting;
    }
@@ -179,6 +182,13 @@ private:
        // the removed ident. If index >=0, ident is present and successfully removed.
        ssize_t removeBatchParamsForIdent(void* ident);

        bool hasBatchParamsForIdent(void* ident) const {
            return batchParams.indexOfKey(ident) >= 0;
        }

        /**
         * @return The number of active clients of this sensor.
         */
        int numActiveClients() const;
    };
    DefaultKeyedVector<int, Info> mActivationCount;
@@ -187,8 +197,26 @@ private:
    SensorServiceUtil::RingBuffer<HidlTransportErrorLog> mHidlTransportErrors;
    int mTotalHidlTransportErrors;

    // Use this vector to determine which client is activated or deactivated.
    SortedVector<void *> mDisabledClients;
    /**
     * Enums describing the reason why a client was disabled.
     */
    enum DisabledReason : uint8_t {
        // UID becomes idle (e.g. app goes to background).
        DISABLED_REASON_UID_IDLE = 0,

        // Sensors are restricted for all clients.
        DISABLED_REASON_SERVICE_RESTRICTED,
        DISABLED_REASON_MAX,
    };

    static_assert(DisabledReason::DISABLED_REASON_MAX < sizeof(uint8_t) * CHAR_BIT);

    // Use this map to determine which client is activated or deactivated.
    std::unordered_map<void *, uint8_t> mDisabledClients;

    void addDisabledReasonForIdentLocked(void* ident, DisabledReason reason);
    void removeDisabledReasonForIdentLocked(void* ident, DisabledReason reason);

    SensorDevice();
    bool connectHidlService();
    void initializeSensorList();
@@ -214,6 +242,9 @@ private:
    status_t batchLocked(void* ident, int handle, int flags, int64_t samplingPeriodNs,
                         int64_t maxBatchReportLatencyNs);

    status_t updateBatchParamsLocked(int handle, Info& info);
    status_t doActivateHardwareLocked(int handle, bool enable);

    void handleHidlDeath(const std::string &detail);
    template<typename T>
    void checkReturn(const Return<T>& ret) {
@@ -225,8 +256,11 @@ private:
    //TODO(b/67425500): remove waiter after bug is resolved.
    sp<SensorDeviceUtils::HidlServiceRegistrationWaiter> mRestartWaiter;

    bool isClientDisabled(void* ident);
    bool isClientDisabledLocked(void* ident);
    bool isClientDisabled(void* ident) const;
    bool isClientDisabledLocked(void* ident) const;
    std::vector<void *> getDisabledClientsLocked() const;

    bool clientHasNoAccessLocked(void* ident) const;

    using Event = hardware::sensors::V2_1::Event;
    using SensorInfo = hardware::sensors::V2_1::SensorInfo;
+4 −9
Original line number Diff line number Diff line
@@ -31,12 +31,11 @@ namespace android {

SensorService::SensorEventConnection::SensorEventConnection(
        const sp<SensorService>& service, uid_t uid, String8 packageName, bool isDataInjectionMode,
        const String16& opPackageName, bool hasSensorAccess)
        const String16& opPackageName)
    : mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false),
      mDead(false), mDataInjectionMode(isDataInjectionMode), mEventCache(nullptr),
      mCacheSize(0), mMaxCacheSize(0), mTimeOfLastEventDrop(0), mEventsDropped(0),
      mPackageName(packageName), mOpPackageName(opPackageName), mDestroyed(false),
      mHasSensorAccess(hasSensorAccess) {
      mPackageName(packageName), mOpPackageName(opPackageName), mDestroyed(false) {
    mChannel = new BitTube(mService->mSocketBufferSize);
#if DEBUG_CONNECTIONS
    mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
@@ -431,13 +430,9 @@ status_t SensorService::SensorEventConnection::sendEvents(
    return size < 0 ? status_t(size) : status_t(NO_ERROR);
}

void SensorService::SensorEventConnection::setSensorAccess(const bool hasAccess) {
    Mutex::Autolock _l(mConnectionLock);
    mHasSensorAccess = hasAccess;
}

bool SensorService::SensorEventConnection::hasSensorAccess() {
    return mHasSensorAccess && !mService->mSensorPrivacyPolicy->isSensorPrivacyEnabled();
    return mService->isUidActive(mUid)
        && !mService->mSensorPrivacyPolicy->isSensorPrivacyEnabled();
}

bool SensorService::SensorEventConnection::noteOpIfRequired(const sensors_event_t& event) {
+1 −5
Original line number Diff line number Diff line
@@ -49,8 +49,7 @@ class SensorService::SensorEventConnection:

public:
    SensorEventConnection(const sp<SensorService>& service, uid_t uid, String8 packageName,
                          bool isDataInjectionMode, const String16& opPackageName,
                          bool hasSensorAccess);
                          bool isDataInjectionMode, const String16& opPackageName);

    status_t sendEvents(sensors_event_t const* buffer, size_t count, sensors_event_t* scratch,
                        wp<const SensorEventConnection> const * mapFlushEventsToConnections = nullptr);
@@ -69,8 +68,6 @@ public:

    uid_t getUid() const { return mUid; }

    void setSensorAccess(const bool hasAccess);

private:
    virtual ~SensorEventConnection();
    virtual void onFirstRef();
@@ -185,7 +182,6 @@ private:

    mutable Mutex mDestroyLock;
    bool mDestroyed;
    bool mHasSensorAccess;

    // Store a mapping of sensor handles to required AppOp for a sensor. This map only contains a
    // valid mapping for sensors that require a permission in order to reduce the lookup time.
+12 −7
Original line number Diff line number Diff line
@@ -299,11 +299,13 @@ void SensorService::onFirstRef() {
    }
}

void SensorService::setSensorAccess(uid_t uid, bool hasAccess) {
void SensorService::onUidStateChanged(uid_t uid, UidState state) {
    SensorDevice& dev(SensorDevice::getInstance());

    ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
    for (const sp<SensorEventConnection>& conn : connLock.getActiveConnections()) {
        if (conn->getUid() == uid) {
            conn->setSensorAccess(hasAccess);
            dev.setUidStateForConnection(conn.get(), state);
        }
    }
}
@@ -1234,9 +1236,8 @@ sp<ISensorEventConnection> SensorService::createSensorEventConnection(const Stri
            (packageName == "") ? String8::format("unknown_package_pid_%d", pid) : packageName;
    String16 connOpPackageName =
            (opPackageName == String16("")) ? String16(connPackageName) : opPackageName;
    bool hasSensorAccess = mUidPolicy->isUidActive(uid);
    sp<SensorEventConnection> result(new SensorEventConnection(this, uid, connPackageName,
            requestedMode == DATA_INJECTION, connOpPackageName, hasSensorAccess));
            requestedMode == DATA_INJECTION, connOpPackageName));
    if (requestedMode == DATA_INJECTION) {
        mConnectionHolder.addEventConnectionIfNotPresent(result);
        // Add the associated file descriptor to the Looper for polling whenever there is data to
@@ -1921,7 +1922,7 @@ void SensorService::UidPolicy::onUidActive(uid_t uid) {
    }
    sp<SensorService> service = mService.promote();
    if (service != nullptr) {
        service->setSensorAccess(uid, true);
        service->onUidStateChanged(uid, UID_STATE_ACTIVE);
    }
}

@@ -1936,7 +1937,7 @@ void SensorService::UidPolicy::onUidIdle(uid_t uid, __unused bool disabled) {
    if (deleted) {
        sp<SensorService> service = mService.promote();
        if (service != nullptr) {
            service->setSensorAccess(uid, false);
            service->onUidStateChanged(uid, UID_STATE_IDLE);
        }
    }
}
@@ -1964,7 +1965,7 @@ void SensorService::UidPolicy::updateOverrideUid(uid_t uid, bool active, bool in
    if (wasActive != isActive) {
        sp<SensorService> service = mService.promote();
        if (service != nullptr) {
            service->setSensorAccess(uid, isActive);
            service->onUidStateChanged(uid, isActive ? UID_STATE_ACTIVE : UID_STATE_IDLE);
        }
    }
}
@@ -1990,6 +1991,10 @@ bool SensorService::UidPolicy::isUidActiveLocked(uid_t uid) {
    return mActiveUids.find(uid) != mActiveUids.end();
}

bool SensorService::isUidActive(uid_t uid) {
    return mUidPolicy->isUidActive(uid);
}

void SensorService::SensorPrivacyPolicy::registerSelf() {
    SensorPrivacyManager spm;
    mSensorPrivacyEnabled = spm.isSensorPrivacyEnabled();
Loading