Merge changes from topic "sensor_sampling_rate_throttling-sc-dev" into sc-dev

* changes:
  Update sensor get methods related to sampling rate
  Resample sensor events for non-direct connections.
  Subscribe to the microphone toggle state.
  Throttle sensor sampling rates at 200Hz.
  Add support for retrieving the Debuggable flag.
diff --git a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
index 889e15a..a7a6563 100644
--- a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
+++ b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
@@ -108,4 +108,10 @@
      * has been set to {@link PackageManager#CERT_INPUT_SHA256}.
      */
     boolean hasSha256SigningCertificate(in @utf8InCpp String packageName, in byte[] certificate);
+
+    /**
+     * Returns the debug flag for the given package.
+     * Unknown packages will cause the call to fail.
+     */
+     boolean isPackageDebuggable(in String packageName);
 }
diff --git a/libs/sensor/Sensor.cpp b/libs/sensor/Sensor.cpp
index 9d817ae..240738d 100644
--- a/libs/sensor/Sensor.cpp
+++ b/libs/sensor/Sensor.cpp
@@ -468,6 +468,19 @@
     mUuid.i64[1] = 0;
 }
 
+void Sensor::capMinDelayMicros(int32_t cappedMinDelay) {
+    if (mMinDelay < cappedMinDelay) {
+        mMinDelay = cappedMinDelay;
+    }
+}
+
+void Sensor::capHighestDirectReportRateLevel(int32_t cappedRateLevel) {
+    if (cappedRateLevel < getHighestDirectReportRateLevel()) {
+        mFlags &= ~SENSOR_FLAG_MASK_DIRECT_REPORT;
+        mFlags |= cappedRateLevel << SENSOR_FLAG_SHIFT_DIRECT_REPORT;
+    }
+}
+
 int32_t Sensor::getId() const {
     return int32_t(mUuid.i64[0]);
 }
diff --git a/libs/sensor/include/sensor/Sensor.h b/libs/sensor/include/sensor/Sensor.h
index 324d443..374b68f 100644
--- a/libs/sensor/include/sensor/Sensor.h
+++ b/libs/sensor/include/sensor/Sensor.h
@@ -104,6 +104,9 @@
     int32_t getId() const;
     void setId(int32_t id);
 
+    void capMinDelayMicros(int32_t cappedMinDelay);
+    void capHighestDirectReportRateLevel(int32_t cappedRateLevel);
+
     // LightFlattenable protocol
     inline bool isFixedSize() const { return false; }
     size_t getFlattenedSize() const;
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 2810bff..23893ea 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -914,6 +914,21 @@
     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);
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 5e7d3da..75da7bb 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -125,6 +125,10 @@
 
     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;
diff --git a/services/sensorservice/SensorDirectConnection.cpp b/services/sensorservice/SensorDirectConnection.cpp
index e4c33da..af86d09 100644
--- a/services/sensorservice/SensorDirectConnection.cpp
+++ b/services/sensorservice/SensorDirectConnection.cpp
@@ -32,6 +32,8 @@
         : mService(service), mUid(uid), mMem(*mem),
         mHalChannelHandle(halChannelHandle),
         mOpPackageName(opPackageName), mDestroyed(false) {
+    mIsRateCappedBasedOnPermission = mService->isRateCappedBasedOnPermission(mOpPackageName);
+    mUserId = multiuser_get_user_id(mUid);
     ALOGD_IF(DEBUG_CONNECTIONS, "Created SensorDirectConnection");
 }
 
@@ -101,6 +103,14 @@
     }
 }
 
+void SensorService::SensorDirectConnection::onMicSensorAccessChanged(bool isMicToggleOn) {
+    if (isMicToggleOn) {
+        capRates();
+    } else {
+        uncapRates();
+    }
+}
+
 bool SensorService::SensorDirectConnection::hasSensorAccess() const {
     return mService->hasSensorAccess(mUid, mOpPackageName);
 }
@@ -134,6 +144,7 @@
 
     if (handle == -1 && rateLevel == SENSOR_DIRECT_RATE_STOP) {
         stopAll();
+        mMicRateBackup.clear();
         return NO_ERROR;
     }
 
@@ -157,6 +168,14 @@
         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) {
+            return err;
+        }
+    }
+
     struct sensors_direct_cfg_t config = {
         .rate_level = rateLevel
     };
@@ -168,18 +187,100 @@
     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);
diff --git a/services/sensorservice/SensorDirectConnection.h b/services/sensorservice/SensorDirectConnection.h
index 4181b65..a3f348b 100644
--- a/services/sensorservice/SensorDirectConnection.h
+++ b/services/sensorservice/SensorDirectConnection.h
@@ -50,6 +50,8 @@
     // 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 @@
     // 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,9 +98,12 @@
     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
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index 6810c1b7..a2e7f23 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -44,6 +44,8 @@
       mCacheSize(0), mMaxCacheSize(0), mTimeOfLastEventDrop(0), mEventsDropped(0),
       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;
@@ -285,6 +287,29 @@
     }
 }
 
+// TODO(b/179649922): A better algorithm to guarantee that capped connections will get a sampling
+// rate close to 200 Hz. With the current algorithm, apps might be punished unfairly: E.g.,two apps
+// make requests to the sensor service at the same time, one is not capped and uses 250 Hz, and one
+//is capped, the capped connection will only get 125 Hz.
+void SensorService::SensorEventConnection::addSensorEventsToBuffer(bool shouldResample,
+    const sensors_event_t& sensorEvent, sensors_event_t* buffer, int* index) {
+    if (!shouldResample || !mService->isSensorInCappedSet(sensorEvent.type)) {
+        buffer[(*index)++] = sensorEvent;
+    } else {
+        int64_t lastTimestamp = -1;
+        auto entry = mSensorLastTimestamp.find(sensorEvent.sensor);
+        if (entry != mSensorLastTimestamp.end()) {
+            lastTimestamp = entry->second;
+        }
+        // Allow 10% headroom here because the clocks are not perfect.
+        if (lastTimestamp == -1  || sensorEvent.timestamp - lastTimestamp
+                                        >= 0.9 * SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS) {
+            mSensorLastTimestamp[sensorEvent.sensor] = sensorEvent.timestamp;
+            buffer[(*index)++] = sensorEvent;
+        }
+    }
+}
+
 status_t SensorService::SensorEventConnection::sendEvents(
         sensors_event_t const* buffer, size_t numEvents,
         sensors_event_t* scratch,
@@ -293,6 +318,8 @@
 
     std::unique_ptr<sensors_event_t[]> sanitizedBuffer;
 
+    bool shouldResample = mService->isMicSensorPrivacyEnabledForUid(mUid) ||
+                            mIsRateCappedBasedOnPermission;
     int count = 0;
     Mutex::Autolock _l(mConnectionLock);
     if (scratch) {
@@ -346,7 +373,7 @@
                     // Regular sensor event, just copy it to the scratch buffer after checking
                     // the AppOp.
                     if (hasSensorAccess() && noteOpIfRequired(buffer[i])) {
-                        scratch[count++] = buffer[i];
+                        addSensorEventsToBuffer(shouldResample, buffer[i], scratch, &count);
                     }
                 }
                 i++;
@@ -356,12 +383,13 @@
                                         buffer[i].meta_data.sensor == sensor_handle)));
         }
     } else {
+        sanitizedBuffer.reset(new sensors_event_t[numEvents]);
+        scratch = sanitizedBuffer.get();
         if (hasSensorAccess()) {
-            scratch = const_cast<sensors_event_t *>(buffer);
-            count = numEvents;
+            for (size_t i = 0; i < numEvents; i++) {
+                addSensorEventsToBuffer(shouldResample, buffer[i], scratch, &count);
+            }
         } else {
-            sanitizedBuffer.reset(new sensors_event_t[numEvents]);
-            scratch = sanitizedBuffer.get();
             for (size_t i = 0; i < numEvents; i++) {
                 if (buffer[i].type == SENSOR_TYPE_META_DATA) {
                     scratch[count++] = buffer[i++];
@@ -684,24 +712,118 @@
 
     status_t err;
     if (enabled) {
+        nsecs_t requestedSamplingPeriodNs = samplingPeriodNs;
+        bool isSensorCapped = false;
+        sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
+        if (si != nullptr) {
+            const Sensor& s = si->getSensor();
+            if (mService->isSensorInCappedSet(s.getType())) {
+                isSensorCapped = true;
+            }
+        }
+        if (isSensorCapped) {
+            err = mService->adjustSamplingPeriodBasedOnMicAndPermission(&samplingPeriodNs,
+                                String16(mOpPackageName));
+            if (err != OK) {
+                return err;
+            }
+        }
         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;
 }
 
-status_t SensorService::SensorEventConnection::setEventRate(
-        int handle, nsecs_t samplingPeriodNs)
-{
+status_t SensorService::SensorEventConnection::setEventRate(int handle, nsecs_t samplingPeriodNs) {
     if (mDestroyed) {
         android_errorWriteLog(0x534e4554, "168211968");
         return DEAD_OBJECT;
     }
 
-    return mService->setEventRate(this, handle, samplingPeriodNs, mOpPackageName);
+    nsecs_t requestedSamplingPeriodNs = samplingPeriodNs;
+    bool isSensorCapped = false;
+    sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
+    if (si != nullptr) {
+        const Sensor& s = si->getSensor();
+        if (mService->isSensorInCappedSet(s.getType())) {
+            isSensorCapped = true;
+        }
+    }
+    if (isSensorCapped) {
+        status_t err = mService->adjustSamplingPeriodBasedOnMicAndPermission(&samplingPeriodNs,
+                            String16(mOpPackageName));
+        if (err != OK) {
+            return err;
+        }
+    }
+    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() {
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index 9487a39..7bd9d47 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -68,6 +68,9 @@
     String8 getPackageName() const;
 
     uid_t getUid() const { return mUid; }
+    // cap/uncap existing connection depending on the state of the mic toggle.
+    void onMicSensorAccessChanged(bool isMicToggleOn);
+    userid_t getUserId() const { return mUserId; }
 
 private:
     virtual ~SensorEventConnection();
@@ -137,10 +140,20 @@
 
     // Call noteOp for the sensor if the sensor requires a permission
     bool noteOpIfRequired(const sensors_event_t& event);
+    // Limits all active connections when the mic toggle is flipped to on.
+    void capRates();
+    // Recover sensor connection previously capped by capRates().
+    void uncapRates();
 
+    // Add sensorEvent to buffer at position index if the sensorEvent satisfies throttling rules.
+    void addSensorEventsToBuffer(bool shouldResample, const sensors_event_t& sensorEvent,
+                        sensors_event_t* buffer, int* index);
     sp<SensorService> const mService;
     sp<BitTube> mChannel;
     uid_t mUid;
+    std::atomic_bool mIsRateCappedBasedOnPermission;
+    // Store a mapping of sensor to the timestamp of their last sensor event.
+    std::unordered_map<int, int64_t> mSensorLastTimestamp;
     mutable Mutex mConnectionLock;
     // Number of events from wake up sensors which are still pending and haven't been delivered to
     // the corresponding application. It is incremented by one unit for each write to the socket.
@@ -189,6 +202,9 @@
     // 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.
     std::unordered_map<int32_t, int32_t> mHandleToAppOp;
+    // Mapping of sensor handles to its rate before being capped by the mic toggle.
+    std::unordered_map<int, nsecs_t> mMicSamplingPeriodBackup;
+    userid_t mUserId;
 };
 
 } // namepsace android
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 8f25bdb..89d1c42 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include <android-base/strings.h>
 #include <android/content/pm/IPackageManagerNative.h>
 #include <android/util/ProtoOutputStream.h>
 #include <frameworks/base/core/proto/android/service/sensor_service.proto.h>
@@ -88,6 +89,8 @@
 #define SENSOR_SERVICE_SCHED_FIFO_PRIORITY 10
 
 // Permissions.
+static const String16 sAccessHighSensorSamplingRatePermission(
+        "android.permission.HIGH_SAMPLING_RATE_SENSORS");
 static const String16 sDumpPermission("android.permission.DUMP");
 static const String16 sLocationHardwarePermission("android.permission.LOCATION_HARDWARE");
 static const String16 sManageSensorsPermission("android.permission.MANAGE_SENSORS");
@@ -366,6 +369,9 @@
     }
     mUidPolicy->unregisterSelf();
     mSensorPrivacyPolicy->unregisterSelf();
+    for (auto const& [userId, policy] : mMicSensorPrivacyPolicies) {
+        policy->unregisterSelf();
+    }
 }
 
 status_t SensorService::dump(int fd, const Vector<String16>& args) {
@@ -695,6 +701,35 @@
     }
 }
 
+void SensorService::capRates(userid_t userId) {
+    ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+    for (const sp<SensorDirectConnection>& conn : connLock.getDirectConnections()) {
+        if (conn->getUserId() == userId) {
+            conn->onMicSensorAccessChanged(true);
+        }
+    }
+
+    for (const sp<SensorEventConnection>& conn : connLock.getActiveConnections()) {
+        if (conn->getUserId() == userId) {
+            conn->onMicSensorAccessChanged(true);
+        }
+    }
+}
+
+void SensorService::uncapRates(userid_t userId) {
+    ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+    for (const sp<SensorDirectConnection>& conn : connLock.getDirectConnections()) {
+        if (conn->getUserId() == userId) {
+            conn->onMicSensorAccessChanged(false);
+        }
+    }
+
+    for (const sp<SensorEventConnection>& conn : connLock.getActiveConnections()) {
+        if (conn->getUserId() == userId) {
+            conn->onMicSensorAccessChanged(false);
+        }
+    }
+}
 
 // NOTE: This is a remote API - make sure all args are validated
 status_t SensorService::shellCommand(int in, int out, int err, Vector<String16>& args) {
@@ -1209,14 +1244,20 @@
     }
 }
 
-Vector<Sensor> SensorService::getSensorList(const String16& /* opPackageName */) {
+Vector<Sensor> SensorService::getSensorList(const String16& opPackageName) {
     char value[PROPERTY_VALUE_MAX];
     property_get("debug.sensors", value, "0");
     const Vector<Sensor>& initialSensorList = (atoi(value)) ?
             mSensors.getUserDebugSensors() : mSensors.getUserSensors();
     Vector<Sensor> accessibleSensorList;
+
+    bool isCapped = isRateCappedBasedOnPermission(opPackageName);
     for (size_t i = 0; i < initialSensorList.size(); i++) {
         Sensor sensor = initialSensorList[i];
+        if (isCapped && isSensorInCappedSet(sensor.getType())) {
+            sensor.capMinDelayMicros(SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS / 1000);
+            sensor.capHighestDirectReportRateLevel(SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL);
+        }
         accessibleSensorList.add(sensor);
     }
     makeUuidsIntoIdsForSensorList(accessibleSensorList);
@@ -2024,6 +2065,69 @@
     return mUidPolicy->isUidActive(uid);
 }
 
+bool SensorService::isRateCappedBasedOnPermission(const String16& opPackageName) {
+    int targetSdk = getTargetSdkVersion(opPackageName);
+    bool hasSamplingRatePermission = PermissionCache::checkCallingPermission(
+                    sAccessHighSensorSamplingRatePermission);
+    if (targetSdk < __ANDROID_API_S__ ||
+            (targetSdk >= __ANDROID_API_S__ && hasSamplingRatePermission)) {
+        return false;
+    }
+    return true;
+}
+
+bool SensorService::isSensorInCappedSet(int sensorType) {
+    return (sensorType == SENSOR_TYPE_ACCELEROMETER
+            || sensorType == SENSOR_TYPE_ACCELEROMETER_UNCALIBRATED
+            || sensorType == SENSOR_TYPE_GYROSCOPE
+            || sensorType == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED
+            || sensorType == SENSOR_TYPE_MAGNETIC_FIELD
+            || sensorType == SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED);
+}
+
+status_t SensorService::adjustSamplingPeriodBasedOnMicAndPermission(nsecs_t* requestedPeriodNs,
+        const String16& opPackageName) {
+    uid_t uid = IPCThreadState::self()->getCallingUid();
+    bool shouldCapBasedOnPermission = isRateCappedBasedOnPermission(opPackageName);
+    if (*requestedPeriodNs >= SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS) {
+        return OK;
+    }
+    if (shouldCapBasedOnPermission) {
+        *requestedPeriodNs = SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS;
+        if (isPackageDebuggable(opPackageName)) {
+            return PERMISSION_DENIED;
+        }
+        return OK;
+    }
+    if (isMicSensorPrivacyEnabledForUid(uid)) {
+        *requestedPeriodNs = SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS;
+        return OK;
+    }
+    return OK;
+}
+
+status_t SensorService::adjustRateLevelBasedOnMicAndPermission(int* requestedRateLevel,
+        const String16& opPackageName) {
+    uid_t uid = IPCThreadState::self()->getCallingUid();
+    bool shouldCapBasedOnPermission = isRateCappedBasedOnPermission(opPackageName);
+
+    if (*requestedRateLevel <= SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL) {
+        return OK;
+    }
+    if (shouldCapBasedOnPermission) {
+        *requestedRateLevel = SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL;
+        if (isPackageDebuggable(opPackageName)) {
+            return PERMISSION_DENIED;
+        }
+        return OK;
+    }
+    if (isMicSensorPrivacyEnabledForUid(uid)) {
+        *requestedRateLevel = SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL;
+        return OK;
+    }
+    return OK;
+}
+
 void SensorService::SensorPrivacyPolicy::registerSelf() {
     SensorPrivacyManager spm;
     mSensorPrivacyEnabled = spm.isSensorPrivacyEnabled();
@@ -2042,16 +2146,56 @@
 binder::Status SensorService::SensorPrivacyPolicy::onSensorPrivacyChanged(bool enabled) {
     mSensorPrivacyEnabled = enabled;
     sp<SensorService> service = mService.promote();
+
     if (service != nullptr) {
-        if (enabled) {
-            service->disableAllSensors();
+        if (mIsIndividualMic) {
+            if (enabled) {
+                service->capRates(mUserId);
+            } else {
+                service->uncapRates(mUserId);
+            }
         } else {
-            service->enableAllSensors();
+            if (enabled) {
+                service->disableAllSensors();
+            } else {
+                service->enableAllSensors();
+            }
         }
     }
     return binder::Status::ok();
 }
 
+status_t SensorService::SensorPrivacyPolicy::registerSelfForIndividual(int userId) {
+    Mutex::Autolock _l(mSensorPrivacyLock);
+
+    SensorPrivacyManager spm;
+    status_t err = spm.addIndividualSensorPrivacyListener(userId,
+            SensorPrivacyManager::INDIVIDUAL_SENSOR_MICROPHONE, this);
+
+    if (err != OK) {
+        ALOGE("Cannot register a mic listener.");
+        return err;
+    }
+    mSensorPrivacyEnabled = spm.isIndividualSensorPrivacyEnabled(userId,
+                SensorPrivacyManager::INDIVIDUAL_SENSOR_MICROPHONE);
+
+    mIsIndividualMic = true;
+    mUserId = userId;
+    return OK;
+}
+
+bool SensorService::isMicSensorPrivacyEnabledForUid(uid_t uid) {
+    userid_t userId = multiuser_get_user_id(uid);
+    if (mMicSensorPrivacyPolicies.find(userId) == mMicSensorPrivacyPolicies.end()) {
+        sp<SensorPrivacyPolicy> userPolicy = new SensorPrivacyPolicy(this);
+        if (userPolicy->registerSelfForIndividual(userId) != OK) {
+            return false;
+        }
+        mMicSensorPrivacyPolicies[userId] = userPolicy;
+    }
+    return mMicSensorPrivacyPolicies[userId]->isSensorPrivacyEnabled();
+}
+
 SensorService::ConnectionSafeAutolock::ConnectionSafeAutolock(
         SensorService::SensorConnectionHolder& holder, Mutex& mutex)
         : mConnectionHolder(holder), mAutolock(mutex) {}
@@ -2109,4 +2253,17 @@
     return ConnectionSafeAutolock(*this, mutex);
 }
 
+bool SensorService::isPackageDebuggable(const String16& opPackageName) {
+    bool debugMode = false;
+    sp<IBinder> binder = defaultServiceManager()->getService(String16("package_native"));
+    if (binder != nullptr) {
+        sp<content::pm::IPackageManagerNative> packageManager =
+                interface_cast<content::pm::IPackageManagerNative>(binder);
+        if (packageManager != nullptr) {
+            binder::Status status = packageManager->isPackageDebuggable(
+                opPackageName, &debugMode);
+        }
+    }
+    return debugMode;
+}
 } // namespace android
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 50c7c2f..dc1463b 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -61,6 +61,15 @@
 
 #define SENSOR_REGISTRATIONS_BUF_SIZE 200
 
+// Apps that targets S+ and do not have HIGH_SAMPLING_RATE_SENSORS permission will be capped
+// at 200 Hz. The cap also applies to all requests when the mic toggle is flipped to on, regardless
+// of their target SDKs and permission.
+// Capped sampling periods for apps that have non-direct sensor connections.
+#define SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS (5 * 1000 * 1000)
+// Capped sampling rate level for apps that have direct sensor connections.
+// The enum SENSOR_DIRECT_RATE_NORMAL corresponds to a rate value of at most 110 Hz.
+#define SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL SENSOR_DIRECT_RATE_NORMAL
+
 namespace android {
 // ---------------------------------------------------------------------------
 class SensorInterface;
@@ -95,6 +104,8 @@
     status_t flushSensor(const sp<SensorEventConnection>& connection,
                          const String16& opPackageName);
 
+    // Returns true if a sensor should be throttled according to our rate-throttling rules.
+    static bool isSensorInCappedSet(int sensorType);
 
     virtual status_t shellCommand(int in, int out, int err, Vector<String16>& args);
 
@@ -216,13 +227,18 @@
             void registerSelf();
             void unregisterSelf();
 
+            status_t registerSelfForIndividual(int userId);
+
             bool isSensorPrivacyEnabled();
 
             binder::Status onSensorPrivacyChanged(bool enabled);
 
         private:
             wp<SensorService> mService;
+            Mutex mSensorPrivacyLock;
             std::atomic_bool mSensorPrivacyEnabled;
+            bool mIsIndividualMic;
+            userid_t mUserId;
     };
 
     enum Mode {
@@ -346,6 +362,13 @@
     // whitelisted). mLock must be held to invoke this method.
     bool isOperationRestrictedLocked(const String16& opPackageName);
 
+    status_t adjustSamplingPeriodBasedOnMicAndPermission(nsecs_t* requestedPeriodNs,
+                                                    const String16& opPackageName);
+    status_t adjustRateLevelBasedOnMicAndPermission(int* requestedRateLevel,
+                                              const String16& opPackageName);
+    bool isRateCappedBasedOnPermission(const String16& opPackageName);
+    bool isPackageDebuggable(const String16& opPackageName);
+
     // Reset the state of SensorService to NORMAL mode.
     status_t resetToNormalMode();
     status_t resetToNormalModeLocked();
@@ -385,6 +408,11 @@
     void enableAllSensors();
     void enableAllSensorsLocked(ConnectionSafeAutolock* connLock);
 
+    // Caps active direct connections (when the mic toggle is flipped to on)
+    void capRates(userid_t userId);
+    // Removes the capped rate on active direct connections (when the mic toggle is flipped to off)
+    void uncapRates(userid_t userId);
+
     static uint8_t sHmacGlobalKey[128];
     static bool sHmacGlobalKeyIsValid;
 
@@ -426,6 +454,11 @@
     static std::map<String16, int> sPackageTargetVersion;
     static Mutex sPackageTargetVersionLock;
     static String16 sSensorInterfaceDescriptorPrefix;
+
+    // Map from user to SensorPrivacyPolicy
+    std::map<userid_t, sp<SensorPrivacyPolicy>> mMicSensorPrivacyPolicies;
+    // Checks if the mic sensor privacy is enabled for the uid
+    bool isMicSensorPrivacyEnabledForUid(uid_t uid);
 };
 
 } // namespace android