diff options
author | 2018-12-04 22:34:29 -0800 | |
---|---|---|
committer | 2018-12-14 11:23:50 -0800 | |
commit | 5e1f60baca875f992a1c5870c1e9a0e5a3107f25 (patch) | |
tree | a3961abdca81732db1019407f0be5d9e6f2e30e4 | |
parent | ae7455153e95f8898bc9558969e09a354fe9dc15 (diff) |
Block access to sensors when Sensor Privacy Mode enabled
Test: manually verified sensor access based on state of sensor privacy
mode.
Bug: 110842805
Change-Id: I4f2f2496356ff4a407e5c0cd32bc0abcf0c8b48f
-rw-r--r-- | libs/sensorprivacy/Android.bp | 47 | ||||
-rw-r--r-- | libs/sensorprivacy/SensorPrivacyManager.cpp | 88 | ||||
-rw-r--r-- | libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyListener.aidl | 24 | ||||
-rw-r--r-- | libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyManager.aidl | 30 | ||||
-rw-r--r-- | libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h | 47 | ||||
-rw-r--r-- | services/sensorservice/Android.bp | 6 | ||||
-rw-r--r-- | services/sensorservice/SensorEventConnection.cpp | 12 | ||||
-rw-r--r-- | services/sensorservice/SensorEventConnection.h | 4 | ||||
-rw-r--r-- | services/sensorservice/SensorService.cpp | 114 | ||||
-rw-r--r-- | services/sensorservice/SensorService.h | 33 |
10 files changed, 376 insertions, 29 deletions
diff --git a/libs/sensorprivacy/Android.bp b/libs/sensorprivacy/Android.bp new file mode 100644 index 0000000000..e0e3469fbb --- /dev/null +++ b/libs/sensorprivacy/Android.bp @@ -0,0 +1,47 @@ +// Copyright 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +cc_library_shared { + name: "libsensorprivacy", + + aidl: { + export_aidl_headers: true, + local_include_dirs: ["aidl"], + }, + + cflags: [ + "-Wall", + "-Wextra", + "-Werror", + "-Wzero-as-null-pointer-constant", + ], + + srcs: [ + "aidl/android/hardware/ISensorPrivacyListener.aidl", + "aidl/android/hardware/ISensorPrivacyManager.aidl", + "SensorPrivacyManager.cpp", + ], + + shared_libs: [ + "libbinder", + "libcutils", + "libutils", + "liblog", + "libhardware", + ], + + export_include_dirs: ["include"], + + export_shared_lib_headers: ["libbinder"], +} diff --git a/libs/sensorprivacy/SensorPrivacyManager.cpp b/libs/sensorprivacy/SensorPrivacyManager.cpp new file mode 100644 index 0000000000..1da79a0c8e --- /dev/null +++ b/libs/sensorprivacy/SensorPrivacyManager.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <mutex> +#include <unistd.h> + +#include <binder/Binder.h> +#include <binder/IServiceManager.h> +#include <sensorprivacy/SensorPrivacyManager.h> + +#include <utils/SystemClock.h> + +namespace android { + +SensorPrivacyManager::SensorPrivacyManager() +{ +} + +sp<hardware::ISensorPrivacyManager> SensorPrivacyManager::getService() +{ + std::lock_guard<Mutex> scoped_lock(mLock); + int64_t startTime = 0; + sp<hardware::ISensorPrivacyManager> service = mService; + while (service == nullptr || !IInterface::asBinder(service)->isBinderAlive()) { + sp<IBinder> binder = defaultServiceManager()->checkService(String16("sensor_privacy")); + if (binder == nullptr) { + // Wait for the sensor privacy service to come back... + if (startTime == 0) { + startTime = uptimeMillis(); + ALOGI("Waiting for sensor privacy service"); + } else if ((uptimeMillis() - startTime) > 1000000) { + ALOGW("Waiting too long for sensor privacy service, giving up"); + service = nullptr; + break; + } + usleep(25000); + } else { + service = interface_cast<hardware::ISensorPrivacyManager>(binder); + mService = service; + } + } + return service; +} + +void SensorPrivacyManager::addSensorPrivacyListener( + const sp<hardware::ISensorPrivacyListener>& listener) +{ + sp<hardware::ISensorPrivacyManager> service = getService(); + if (service != nullptr) { + service->addSensorPrivacyListener(listener); + } +} + +void SensorPrivacyManager::removeSensorPrivacyListener( + const sp<hardware::ISensorPrivacyListener>& listener) +{ + sp<hardware::ISensorPrivacyManager> service = getService(); + if (service != nullptr) { + service->removeSensorPrivacyListener(listener); + } +} + +bool SensorPrivacyManager::isSensorPrivacyEnabled() +{ + sp<hardware::ISensorPrivacyManager> service = getService(); + if (service != nullptr) { + bool result; + service->isSensorPrivacyEnabled(&result); + return result; + } + // if the SensorPrivacyManager is not available then assume sensor privacy is disabled + return false; +} + +}; // namespace android diff --git a/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyListener.aidl b/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyListener.aidl new file mode 100644 index 0000000000..58177d837f --- /dev/null +++ b/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyListener.aidl @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware; + +/** + * @hide + */ +oneway interface ISensorPrivacyListener { + void onSensorPrivacyChanged(boolean enabled); +} diff --git a/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyManager.aidl b/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyManager.aidl new file mode 100644 index 0000000000..4c2d5dbb8f --- /dev/null +++ b/libs/sensorprivacy/aidl/android/hardware/ISensorPrivacyManager.aidl @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware; + +import android.hardware.ISensorPrivacyListener; + +/** @hide */ +interface ISensorPrivacyManager { + void addSensorPrivacyListener(in ISensorPrivacyListener listener); + + void removeSensorPrivacyListener(in ISensorPrivacyListener listener); + + boolean isSensorPrivacyEnabled(); + + void setSensorPrivacy(boolean enable); +} diff --git a/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h b/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h new file mode 100644 index 0000000000..882659598c --- /dev/null +++ b/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_SENSOR_PRIVACY_MANAGER_H +#define ANDROID_SENSOR_PRIVACY_MANAGER_H + +#include "android/hardware/ISensorPrivacyListener.h" +#include "android/hardware/ISensorPrivacyManager.h" + +#include <utils/threads.h> + +// --------------------------------------------------------------------------- +namespace android { + +class SensorPrivacyManager +{ +public: + SensorPrivacyManager(); + + void addSensorPrivacyListener(const sp<hardware::ISensorPrivacyListener>& listener); + void removeSensorPrivacyListener(const sp<hardware::ISensorPrivacyListener>& listener); + bool isSensorPrivacyEnabled(); + +private: + Mutex mLock; + sp<hardware::ISensorPrivacyManager> mService; + sp<hardware::ISensorPrivacyManager> getService(); +}; + + +}; // namespace android +// --------------------------------------------------------------------------- + +#endif // ANDROID_SENSOR_PRIVACY_MANAGER_H diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp index f87fcdc437..33a2747312 100644 --- a/services/sensorservice/Android.bp +++ b/services/sensorservice/Android.bp @@ -41,6 +41,7 @@ cc_library_shared { "liblog", "libbinder", "libsensor", + "libsensorprivacy", "libcrypto", "libbase", "libhidlbase", @@ -53,8 +54,8 @@ cc_library_shared { static_libs: ["android.hardware.sensors@1.0-convert"], - // our public headers depend on libsensor - export_shared_lib_headers: ["libsensor"], + // our public headers depend on libsensor and libsensorprivacy + export_shared_lib_headers: ["libsensor", "libsensorprivacy"], } cc_binary { @@ -64,6 +65,7 @@ cc_binary { shared_libs: [ "libsensorservice", + "libsensorprivacy", "libbinder", "libutils", ], diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp index 776efab19c..b66cbcfbe5 100644 --- a/services/sensorservice/SensorEventConnection.cpp +++ b/services/sensorservice/SensorEventConnection.cpp @@ -279,7 +279,7 @@ status_t SensorService::SensorEventConnection::sendEvents( } } else { // Regular sensor event, just copy it to the scratch buffer. - if (mHasSensorAccess) { + if (hasSensorAccess()) { scratch[count++] = buffer[i]; } } @@ -290,7 +290,7 @@ status_t SensorService::SensorEventConnection::sendEvents( buffer[i].meta_data.sensor == sensor_handle))); } } else { - if (mHasSensorAccess) { + if (hasSensorAccess()) { scratch = const_cast<sensors_event_t *>(buffer); count = numEvents; } else { @@ -321,7 +321,7 @@ status_t SensorService::SensorEventConnection::sendEvents( } int index_wake_up_event = -1; - if (mHasSensorAccess) { + if (hasSensorAccess()) { index_wake_up_event = findWakeUpSensorEventLocked(scratch, count); if (index_wake_up_event >= 0) { scratch[index_wake_up_event].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK; @@ -375,6 +375,10 @@ void SensorService::SensorEventConnection::setSensorAccess(const bool hasAccess) mHasSensorAccess = hasAccess; } +bool SensorService::SensorEventConnection::hasSensorAccess() { + return mHasSensorAccess && !mService->mSensorPrivacyPolicy->isSensorPrivacyEnabled(); +} + void SensorService::SensorEventConnection::reAllocateCacheLocked(sensors_event_t const* scratch, int count) { sensors_event_t *eventCache_new; @@ -491,7 +495,7 @@ void SensorService::SensorEventConnection::writeToSocketFromCache() { for (int numEventsSent = 0; numEventsSent < mCacheSize;) { const int numEventsToWrite = helpers::min(mCacheSize - numEventsSent, maxWriteSize); int index_wake_up_event = -1; - if (mHasSensorAccess) { + if (hasSensorAccess()) { index_wake_up_event = findWakeUpSensorEventLocked(mEventCache + numEventsSent, numEventsToWrite); if (index_wake_up_event >= 0) { diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h index 061809f363..70778806ce 100644 --- a/services/sensorservice/SensorEventConnection.h +++ b/services/sensorservice/SensorEventConnection.h @@ -130,6 +130,10 @@ private: void updateLooperRegistration(const sp<Looper>& looper); void updateLooperRegistrationLocked(const sp<Looper>& looper); + // Returns whether sensor access is available based on both the uid being active and sensor + // privacy not being enabled. + bool hasSensorAccess(); + sp<SensorService> const mService; sp<BitTube> mChannel; uid_t mUid; diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index 85450f813c..9a37ff1902 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -29,6 +29,7 @@ #include <openssl/hmac.h> #include <openssl/rand.h> #include <sensor/SensorEventQueue.h> +#include <sensorprivacy/SensorPrivacyManager.h> #include <utils/SystemClock.h> #include "BatteryService.h" @@ -88,6 +89,7 @@ SensorService::SensorService() : mInitCheck(NO_INIT), mSocketBufferSize(SOCKET_BUFFER_SIZE_NON_BATCHED), mWakeLockAcquired(false) { mUidPolicy = new UidPolicy(this); + mSensorPrivacyPolicy = new SensorPrivacyPolicy(this); } bool SensorService::initializeHmacKey() { @@ -286,6 +288,9 @@ void SensorService::onFirstRef() { // Start watching UID changes to apply policy. mUidPolicy->registerSelf(); + + // Start watching sensor privacy changes + mSensorPrivacyPolicy->registerSelf(); } } } @@ -338,6 +343,7 @@ SensorService::~SensorService() { delete entry.second; } mUidPolicy->unregisterSelf(); + mSensorPrivacyPolicy->unregisterSelf(); } status_t SensorService::dump(int fd, const Vector<String16>& args) { @@ -364,35 +370,16 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) { } mCurrentOperatingMode = RESTRICTED; - // temporarily stop all sensor direct report - for (auto &i : mDirectConnections) { - sp<SensorDirectConnection> connection(i.promote()); - if (connection != nullptr) { - connection->stopAll(true /* backupRecord */); - } - } - - dev.disableAllSensors(); - // Clear all pending flush connections for all active sensors. If one of the active - // connections has called flush() and the underlying sensor has been disabled before a - // flush complete event is returned, we need to remove the connection from this queue. - for (size_t i=0 ; i< mActiveSensors.size(); ++i) { - mActiveSensors.valueAt(i)->clearAllPendingFlushConnections(); - } + // temporarily stop all sensor direct report and disable sensors + disableAllSensorsLocked(); mWhiteListedPackage.setTo(String8(args[1])); return status_t(NO_ERROR); } else if (args.size() == 1 && args[0] == String16("enable")) { // If currently in restricted mode, reset back to NORMAL mode else ignore. if (mCurrentOperatingMode == RESTRICTED) { mCurrentOperatingMode = NORMAL; - dev.enableAllSensors(); - // recover all sensor direct report - for (auto &i : mDirectConnections) { - sp<SensorDirectConnection> connection(i.promote()); - if (connection != nullptr) { - connection->recoverAll(); - } - } + // enable sensors and recover all sensor direct report + enableAllSensorsLocked(); } if (mCurrentOperatingMode == DATA_INJECTION) { resetToNormalModeLocked(); @@ -477,6 +464,8 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) { case DATA_INJECTION: result.appendFormat(" DATA_INJECTION : %s\n", mWhiteListedPackage.string()); } + result.appendFormat("Sensor Privacy: %s\n", + mSensorPrivacyPolicy->isSensorPrivacyEnabled() ? "enabled" : "disabled"); result.appendFormat("%zd active connections\n", mActiveConnections.size()); for (size_t i=0 ; i < mActiveConnections.size() ; i++) { @@ -519,6 +508,52 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) { return NO_ERROR; } +void SensorService::disableAllSensors() { + Mutex::Autolock _l(mLock); + disableAllSensorsLocked(); +} + +void SensorService::disableAllSensorsLocked() { + SensorDevice& dev(SensorDevice::getInstance()); + for (auto &i : mDirectConnections) { + sp<SensorDirectConnection> connection(i.promote()); + if (connection != nullptr) { + connection->stopAll(true /* backupRecord */); + } + } + dev.disableAllSensors(); + // Clear all pending flush connections for all active sensors. If one of the active + // connections has called flush() and the underlying sensor has been disabled before a + // flush complete event is returned, we need to remove the connection from this queue. + for (size_t i=0 ; i< mActiveSensors.size(); ++i) { + mActiveSensors.valueAt(i)->clearAllPendingFlushConnections(); + } +} + +void SensorService::enableAllSensors() { + Mutex::Autolock _l(mLock); + enableAllSensorsLocked(); +} + +void SensorService::enableAllSensorsLocked() { + // sensors should only be enabled if the operating state is not restricted and sensor + // privacy is not enabled. + if (mCurrentOperatingMode == RESTRICTED || mSensorPrivacyPolicy->isSensorPrivacyEnabled()) { + ALOGW("Sensors cannot be enabled: mCurrentOperatingMode = %d, sensor privacy = %s", + mCurrentOperatingMode, + mSensorPrivacyPolicy->isSensorPrivacyEnabled() ? "enabled" : "disabled"); + return; + } + SensorDevice& dev(SensorDevice::getInstance()); + dev.enableAllSensors(); + for (auto &i : mDirectConnections) { + sp<SensorDirectConnection> connection(i.promote()); + if (connection != nullptr) { + connection->recoverAll(); + } + } +} + // 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) { if (!checkCallingPermission(sManageSensorsPermission, nullptr, nullptr)) { @@ -1076,6 +1111,12 @@ sp<ISensorEventConnection> SensorService::createSensorDirectConnection( const native_handle *resource) { Mutex::Autolock _l(mLock); + // No new direct connections are allowed when sensor privacy is enabled + if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) { + ALOGE("Cannot create new direct connections when sensor privacy is enabled"); + return nullptr; + } + struct sensors_direct_mem_t mem = { .type = type, .format = format, @@ -1753,4 +1794,31 @@ bool SensorService::UidPolicy::isUidActiveLocked(uid_t uid) { return mActiveUids.find(uid) != mActiveUids.end(); } +void SensorService::SensorPrivacyPolicy::registerSelf() { + SensorPrivacyManager spm; + mSensorPrivacyEnabled = spm.isSensorPrivacyEnabled(); + spm.addSensorPrivacyListener(this); +} + +void SensorService::SensorPrivacyPolicy::unregisterSelf() { + SensorPrivacyManager spm; + spm.removeSensorPrivacyListener(this); +} + +bool SensorService::SensorPrivacyPolicy::isSensorPrivacyEnabled() { + return mSensorPrivacyEnabled; +} + +binder::Status SensorService::SensorPrivacyPolicy::onSensorPrivacyChanged(bool enabled) { + mSensorPrivacyEnabled = enabled; + sp<SensorService> service = mService.promote(); + if (service != nullptr) { + if (enabled) { + service->disableAllSensors(); + } else { + service->enableAllSensors(); + } + } + return binder::Status::ok(); +} }; // namespace android diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h index 24b0dd74be..136ee27131 100644 --- a/services/sensorservice/SensorService.h +++ b/services/sensorservice/SensorService.h @@ -26,6 +26,7 @@ #include <sensor/ISensorServer.h> #include <sensor/ISensorEventConnection.h> #include <sensor/Sensor.h> +#include "android/hardware/BnSensorPrivacyListener.h" #include <utils/AndroidThreads.h> #include <utils/KeyedVector.h> @@ -132,6 +133,30 @@ private: std::unordered_map<uid_t, bool> mOverrideUids; }; + // Sensor privacy allows a user to disable access to all sensors on the device. When + // enabled sensor privacy will prevent all apps, including active apps, from accessing + // sensors, they will not receive trigger nor on-change events, flush event behavior + // does not change, and recurring events are the same as the first one delivered when + // sensor privacy was enabled. All sensor direct connections will be stopped as well + // and new direct connections will not be allowed while sensor privacy is enabled. + // Once sensor privacy is disabled access to sensors will be restored for active + // apps, previously stopped direct connections will be restarted, and new direct + // connections will be allowed again. + class SensorPrivacyPolicy : public hardware::BnSensorPrivacyListener { + public: + explicit SensorPrivacyPolicy(wp<SensorService> service) : mService(service) {} + void registerSelf(); + void unregisterSelf(); + + bool isSensorPrivacyEnabled(); + + binder::Status onSensorPrivacyChanged(bool enabled); + + private: + wp<SensorService> mService; + std::atomic_bool mSensorPrivacyEnabled; + }; + enum Mode { // The regular operating mode where any application can register/unregister/call flush on // sensors. @@ -275,6 +300,13 @@ private: // Prints the shell command help status_t printHelp(int out); + // temporarily stops all active direct connections and disables all sensors + void disableAllSensors(); + void disableAllSensorsLocked(); + // restarts the previously stopped direct connections and enables all sensors + void enableAllSensors(); + void enableAllSensorsLocked(); + static uint8_t sHmacGlobalKey[128]; static bool sHmacGlobalKeyIsValid; @@ -309,6 +341,7 @@ private: Vector<SensorRegistrationInfo> mLastNSensorRegistrations; sp<UidPolicy> mUidPolicy; + sp<SensorPrivacyPolicy> mSensorPrivacyPolicy; }; } // namespace android |