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

Commit 5198c99c authored by Anh Pham's avatar Anh Pham
Browse files

Subscribe to the microphone toggle state.

When the microphone toggle is on, all connections are clamped down to
200 Hz. When the microphone toggle is off, the original rates of
connections are recovered.

Test: atest CtsSensorTestCases CtsSensorRatePermissionTestCases
Bug: 136069189
Change-Id: Ifc446b726c4200e1a1dae5d7c3026238928383dc
parent af91a91c
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -914,6 +914,21 @@ bool SensorDevice::isSensorActive(int handle) const {
    return mActivationCount.valueAt(activationIndex).numActiveClients() > 0;
}

void SensorDevice::onMicSensorAccessChanged(void* ident, int handle, nsecs_t samplingPeriodNs) {
    Mutex::Autolock _l(mLock);
    ssize_t activationIndex = mActivationCount.indexOfKey(handle);
    if (activationIndex < 0) {
        ALOGW("Handle %d cannot be found in activation record", handle);
        return;
    }
    Info& info(mActivationCount.editValueAt(activationIndex));
    if (info.hasBatchParamsForIdent(ident)) {
        ssize_t index = info.batchParams.indexOfKey(ident);
        BatchParams& params = info.batchParams.editValueAt(index);
        params.mTSample = samplingPeriodNs;
    }
}

void SensorDevice::enableAllSensors() {
    if (mSensors == nullptr) return;
    Mutex::Autolock _l(mLock);
+4 −0
Original line number Diff line number Diff line
@@ -125,6 +125,10 @@ public:

    bool isSensorActive(int handle) const;

    // To update the BatchParams of a SensorEventConnection when the mic toggle changes its state
    // while the Sensors Off toggle is on.
    void onMicSensorAccessChanged(void* ident, int handle, nsecs_t samplingPeriodNs);

    // Dumpable
    virtual std::string dump() const override;
    virtual void dump(util::ProtoOutputStream* proto) const override;
+93 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ SensorService::SensorDirectConnection::SensorDirectConnection(const sp<SensorSer
        mHalChannelHandle(halChannelHandle),
        mOpPackageName(opPackageName), mDestroyed(false) {
    mIsRateCappedBasedOnPermission = mService->isRateCappedBasedOnPermission(mOpPackageName);
    mUserId = multiuser_get_user_id(mUid);
    ALOGD_IF(DEBUG_CONNECTIONS, "Created SensorDirectConnection");
}

@@ -102,6 +103,14 @@ void SensorService::SensorDirectConnection::onSensorAccessChanged(bool hasAccess
    }
}

void SensorService::SensorDirectConnection::onMicSensorAccessChanged(bool isMicToggleOn) {
    if (isMicToggleOn) {
        capRates();
    } else {
        uncapRates();
    }
}

bool SensorService::SensorDirectConnection::hasSensorAccess() const {
    return mService->hasSensorAccess(mUid, mOpPackageName);
}
@@ -135,6 +144,7 @@ int32_t SensorService::SensorDirectConnection::configureChannel(int handle, int

    if (handle == -1 && rateLevel == SENSOR_DIRECT_RATE_STOP) {
        stopAll();
        mMicRateBackup.clear();
        return NO_ERROR;
    }

@@ -158,6 +168,7 @@ int32_t SensorService::SensorDirectConnection::configureChannel(int handle, int
        return INVALID_OPERATION;
    }

    int requestedRateLevel = rateLevel;
    if (mService->isSensorInCappedSet(s.getType()) && rateLevel != SENSOR_DIRECT_RATE_STOP) {
        status_t err = mService->adjustRateLevelBasedOnMicAndPermission(&rateLevel, mOpPackageName);
        if (err != OK) {
@@ -176,18 +187,100 @@ int32_t SensorService::SensorDirectConnection::configureChannel(int handle, int
    if (rateLevel == SENSOR_DIRECT_RATE_STOP) {
        if (ret == NO_ERROR) {
            mActivated.erase(handle);
            mMicRateBackup.erase(handle);
        } else if (ret > 0) {
            ret = UNKNOWN_ERROR;
        }
    } else {
        if (ret > 0) {
            mActivated[handle] = rateLevel;
            if (mService->isSensorInCappedSet(s.getType())) {
                // Back up the rates that the app is allowed to have if the mic toggle is off
                // This is used in the uncapRates() function.
                if (!mIsRateCappedBasedOnPermission ||
                            requestedRateLevel <= SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL) {
                    mMicRateBackup[handle] = requestedRateLevel;
                } else {
                    mMicRateBackup[handle] = SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL;
                }
            }
        }
    }

    return ret;
}

void SensorService::SensorDirectConnection::capRates() {
    Mutex::Autolock _l(mConnectionLock);
    const struct sensors_direct_cfg_t capConfig = {
        .rate_level = SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL
    };

    const struct sensors_direct_cfg_t stopConfig = {
        .rate_level = SENSOR_DIRECT_RATE_STOP
    };

    // If our requests are in the backup, then we shouldn't activate sensors from here
    bool temporarilyStopped = mActivated.empty() && !mActivatedBackup.empty();
    std::unordered_map<int, int>& existingConnections =
                    (!temporarilyStopped) ? mActivated : mActivatedBackup;

    SensorDevice& dev(SensorDevice::getInstance());
    for (auto &i : existingConnections) {
        int handle = i.first;
        int rateLevel = i.second;
        sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
        if (si != nullptr) {
            const Sensor& s = si->getSensor();
            if (mService->isSensorInCappedSet(s.getType()) &&
                        rateLevel > SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL) {
                mMicRateBackup[handle] = rateLevel;
                // Modify the rate kept by the existing map
                existingConnections[handle] = SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL;
                // Only reconfigure the channel if it's ongoing
                if (!temporarilyStopped) {
                    // Stopping before reconfiguring is the well-tested path in CTS
                    dev.configureDirectChannel(handle, getHalChannelHandle(), &stopConfig);
                    dev.configureDirectChannel(handle, getHalChannelHandle(), &capConfig);
                }
            }
        }
    }
}

void SensorService::SensorDirectConnection::uncapRates() {
    Mutex::Autolock _l(mConnectionLock);

    // If our requests are in the backup, then we shouldn't activate sensors from here
    bool temporarilyStopped = mActivated.empty() && !mActivatedBackup.empty();
    std::unordered_map<int, int>& existingConnections =
                    (!temporarilyStopped) ? mActivated : mActivatedBackup;

    const struct sensors_direct_cfg_t stopConfig = {
        .rate_level = SENSOR_DIRECT_RATE_STOP
    };
    SensorDevice& dev(SensorDevice::getInstance());
    for (auto &i : mMicRateBackup) {
        int handle = i.first;
        int rateLevel = i.second;

        const struct sensors_direct_cfg_t config = {
            .rate_level = rateLevel
        };

        // Modify the rate kept by the existing map
        existingConnections[handle] = rateLevel;

        // Only reconfigure the channel if it's ongoing
        if (!temporarilyStopped) {
            // Stopping before reconfiguring is the well-tested path in CTS
            dev.configureDirectChannel(handle, getHalChannelHandle(), &stopConfig);
            dev.configureDirectChannel(handle, getHalChannelHandle(), &config);
        }
    }
    mMicRateBackup.clear();
}

void SensorService::SensorDirectConnection::stopAll(bool backupRecord) {
    Mutex::Autolock _l(mConnectionLock);
    stopAllLocked(backupRecord);
+9 −0
Original line number Diff line number Diff line
@@ -50,6 +50,8 @@ public:
    // regained due to changes in the sensor restricted/privacy mode or the
    // app changed to idle/active status.
    void onSensorAccessChanged(bool hasAccess);
    void onMicSensorAccessChanged(bool isMicToggleOn);
    userid_t getUserId() const { return mUserId; }

protected:
    virtual ~SensorDirectConnection();
@@ -82,6 +84,11 @@ private:
    // If no requests are backed up by stopAll(), this method is no-op.
    void recoverAll();

    // Limits all active sensor direct report requests when the mic toggle is flipped to on.
    void capRates();
    // Recover sensor requests previously capped by capRates().
    void uncapRates();

    const sp<SensorService> mService;
    const uid_t mUid;
    const sensors_direct_mem_t mMem;
@@ -91,10 +98,12 @@ private:
    mutable Mutex mConnectionLock;
    std::unordered_map<int, int> mActivated;
    std::unordered_map<int, int> mActivatedBackup;
    std::unordered_map<int, int> mMicRateBackup;

    std::atomic_bool mIsRateCappedBasedOnPermission;
    mutable Mutex mDestroyLock;
    bool mDestroyed;
    userid_t mUserId;
};

} // namepsace android
+68 −1
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ SensorService::SensorEventConnection::SensorEventConnection(
      mPackageName(packageName), mOpPackageName(opPackageName), mTargetSdk(kTargetSdkUnknown),
      mDestroyed(false) {
    mIsRateCappedBasedOnPermission = mService->isRateCappedBasedOnPermission(mOpPackageName);
    mUserId = multiuser_get_user_id(mUid);
    mChannel = new BitTube(mService->mSocketBufferSize);
#if DEBUG_CONNECTIONS
    mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
@@ -685,6 +686,7 @@ status_t SensorService::SensorEventConnection::enableDisable(

    status_t err;
    if (enabled) {
        nsecs_t requestedSamplingPeriodNs = samplingPeriodNs;
        bool isSensorCapped = false;
        sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
        if (si != nullptr) {
@@ -702,9 +704,18 @@ status_t SensorService::SensorEventConnection::enableDisable(
        }
        err = mService->enable(this, handle, samplingPeriodNs, maxBatchReportLatencyNs,
                               reservedFlags, mOpPackageName);
        if (err == OK && isSensorCapped) {
            if (!mIsRateCappedBasedOnPermission ||
                        requestedSamplingPeriodNs >= SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS) {
                mMicSamplingPeriodBackup[handle] = requestedSamplingPeriodNs;
            } else {
                mMicSamplingPeriodBackup[handle] = SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS;
            }
        }

    } else {
        err = mService->disable(this, handle);
        mMicSamplingPeriodBackup.erase(handle);
    }
    return err;
}
@@ -715,6 +726,7 @@ status_t SensorService::SensorEventConnection::setEventRate(int handle, nsecs_t
        return DEAD_OBJECT;
    }

    nsecs_t requestedSamplingPeriodNs = samplingPeriodNs;
    bool isSensorCapped = false;
    sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
    if (si != nullptr) {
@@ -730,7 +742,62 @@ status_t SensorService::SensorEventConnection::setEventRate(int handle, nsecs_t
            return err;
        }
    }
    return mService->setEventRate(this, handle, samplingPeriodNs, mOpPackageName);
    status_t ret = mService->setEventRate(this, handle, samplingPeriodNs, mOpPackageName);
    if (ret == OK && isSensorCapped) {
        if (!mIsRateCappedBasedOnPermission ||
                    requestedSamplingPeriodNs >= SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS) {
            mMicSamplingPeriodBackup[handle] = requestedSamplingPeriodNs;
        } else {
            mMicSamplingPeriodBackup[handle] = SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS;
        }
    }
    return ret;
}

void SensorService::SensorEventConnection::onMicSensorAccessChanged(bool isMicToggleOn) {
    if (isMicToggleOn) {
        capRates();
    } else {
        uncapRates();
    }
}

void SensorService::SensorEventConnection::capRates() {
    Mutex::Autolock _l(mConnectionLock);
    SensorDevice& dev(SensorDevice::getInstance());
    for (auto &i : mMicSamplingPeriodBackup) {
        int handle = i.first;
        nsecs_t samplingPeriodNs = i.second;
        if (samplingPeriodNs < SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS) {
            if (hasSensorAccess()) {
                mService->setEventRate(this, handle, SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS,
                                       mOpPackageName);
            } else {
                // Update SensorDevice with the capped rate so that when sensor access is restored,
                // the correct event rate is used.
                dev.onMicSensorAccessChanged(this, handle,
                                             SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS);
            }
        }
    }
}

void SensorService::SensorEventConnection::uncapRates() {
    Mutex::Autolock _l(mConnectionLock);
    SensorDevice& dev(SensorDevice::getInstance());
    for (auto &i : mMicSamplingPeriodBackup) {
        int handle = i.first;
        nsecs_t samplingPeriodNs = i.second;
        if (samplingPeriodNs < SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS) {
            if (hasSensorAccess()) {
                mService->setEventRate(this, handle, samplingPeriodNs, mOpPackageName);
            } else {
                // Update SensorDevice with the uncapped rate so that when sensor access is
                // restored, the correct event rate is used.
                dev.onMicSensorAccessChanged(this, handle, samplingPeriodNs);
            }
        }
    }
}

status_t  SensorService::SensorEventConnection::flush() {
Loading