diff options
-rw-r--r-- | libs/binder/Android.bp | 1 | ||||
-rw-r--r-- | libs/binder/IPermissionController.cpp | 22 | ||||
-rw-r--r-- | libs/binder/PermissionController.cpp | 82 | ||||
-rw-r--r-- | libs/binder/include/binder/IPermissionController.h | 5 | ||||
-rw-r--r-- | libs/binder/include/binder/PermissionController.h | 55 | ||||
-rw-r--r-- | libs/sensor/ISensorServer.cpp | 25 | ||||
-rw-r--r-- | libs/sensor/include/sensor/ISensorServer.h | 3 | ||||
-rw-r--r-- | services/sensorservice/SensorEventConnection.cpp | 66 | ||||
-rw-r--r-- | services/sensorservice/SensorEventConnection.h | 6 | ||||
-rw-r--r-- | services/sensorservice/SensorService.cpp | 198 | ||||
-rw-r--r-- | services/sensorservice/SensorService.h | 53 |
11 files changed, 493 insertions, 23 deletions
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index 2a07cd1fdb..1dd1e6a891 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -63,6 +63,7 @@ cc_library { "MemoryHeapBase.cpp", "Parcel.cpp", "PermissionCache.cpp", + "PermissionController.cpp", "PersistableBundle.cpp", "ProcessInfoService.cpp", "ProcessState.cpp", diff --git a/libs/binder/IPermissionController.cpp b/libs/binder/IPermissionController.cpp index 674bddf218..ef67ab8dd2 100644 --- a/libs/binder/IPermissionController.cpp +++ b/libs/binder/IPermissionController.cpp @@ -78,6 +78,18 @@ public: if (reply.readExceptionCode() != 0) return false; return reply.readInt32() != 0; } + + virtual int getPackageUid(const String16& package, int flags) + { + Parcel data, reply; + data.writeInterfaceToken(IPermissionController::getInterfaceDescriptor()); + data.writeString16(package); + data.writeInt32(flags); + remote()->transact(GET_PACKAGE_UID_TRANSACTION, data, &reply); + // fail on exception + if (reply.readExceptionCode() != 0) return false; + return reply.readInt32(); + } }; IMPLEMENT_META_INTERFACE(PermissionController, "android.os.IPermissionController"); @@ -122,6 +134,16 @@ status_t BnPermissionController::onTransact( return NO_ERROR; } break; + case GET_PACKAGE_UID_TRANSACTION: { + CHECK_INTERFACE(IPermissionController, data, reply); + String16 package = data.readString16(); + int flags = data.readInt32(); + const int uid = getPackageUid(package, flags); + reply->writeNoException(); + reply->writeInt32(uid); + return NO_ERROR; + } break; + default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/binder/PermissionController.cpp b/libs/binder/PermissionController.cpp new file mode 100644 index 0000000000..25748cadbb --- /dev/null +++ b/libs/binder/PermissionController.cpp @@ -0,0 +1,82 @@ +/* + * 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 <binder/PermissionController.h> +#include <binder/Binder.h> +#include <binder/IServiceManager.h> + +#include <utils/SystemClock.h> + +namespace android { + +PermissionController::PermissionController() +{ +} + +sp<IPermissionController> PermissionController::getService() +{ + std::lock_guard<Mutex> scoped_lock(mLock); + int64_t startTime = 0; + sp<IPermissionController> service = mService; + while (service == nullptr || !IInterface::asBinder(service)->isBinderAlive()) { + sp<IBinder> binder = defaultServiceManager()->checkService(String16("permission")); + if (binder == nullptr) { + // Wait for the activity service to come back... + if (startTime == 0) { + startTime = uptimeMillis(); + ALOGI("Waiting for permission service"); + } else if ((uptimeMillis() - startTime) > 10000) { + ALOGW("Waiting too long for permission service, giving up"); + service = NULL; + break; + } + sleep(1); + } else { + service = interface_cast<IPermissionController>(binder); + mService = service; + } + } + return service; +} + +bool PermissionController::checkPermission(const String16& permission, int32_t pid, int32_t uid) +{ + sp<IPermissionController> service = getService(); + return service != NULL ? service->checkPermission(permission, pid, uid) : false; +} + +void PermissionController::getPackagesForUid(const uid_t uid, Vector<String16> &packages) +{ + sp<IPermissionController> service = getService(); + if (service != nullptr) { + service->getPackagesForUid(uid, packages); + } +} + +bool PermissionController::isRuntimePermission(const String16& permission) +{ + sp<IPermissionController> service = getService(); + return service != nullptr ? service->isRuntimePermission(permission) : false; +} + +int PermissionController::getPackageUid(const String16& package, int flags) +{ + sp<IPermissionController> service = getService(); + return service != nullptr ? service->getPackageUid(package, flags) : -1; +} + +}; // namespace android diff --git a/libs/binder/include/binder/IPermissionController.h b/libs/binder/include/binder/IPermissionController.h index 25f34313f0..2f63677026 100644 --- a/libs/binder/include/binder/IPermissionController.h +++ b/libs/binder/include/binder/IPermissionController.h @@ -36,10 +36,13 @@ public: virtual bool isRuntimePermission(const String16& permission) = 0; + virtual int getPackageUid(const String16& package, int flags) = 0; + enum { CHECK_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, GET_PACKAGES_FOR_UID_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 1, - IS_RUNTIME_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 2 + IS_RUNTIME_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 2, + GET_PACKAGE_UID_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 3 }; }; diff --git a/libs/binder/include/binder/PermissionController.h b/libs/binder/include/binder/PermissionController.h new file mode 100644 index 0000000000..c4c98d02e5 --- /dev/null +++ b/libs/binder/include/binder/PermissionController.h @@ -0,0 +1,55 @@ +/* + * 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_PERMISSION_CONTROLLER_H +#define ANDROID_PERMISSION_CONTROLLER_H + +#include <binder/IPermissionController.h> + +#include <utils/threads.h> + +// --------------------------------------------------------------------------- +namespace android { + +class PermissionController +{ +public: + + enum { + MATCH_SYSTEM_ONLY = 1<<16, + MATCH_UNINSTALLED_PACKAGES = 1<<13, + MATCH_FACTORY_ONLY = 1<<21, + MATCH_INSTANT = 1<<23 + }; + + PermissionController(); + + bool checkPermission(const String16& permission, int32_t pid, int32_t uid); + void getPackagesForUid(const uid_t uid, Vector<String16>& packages); + bool isRuntimePermission(const String16& permission); + int getPackageUid(const String16& package, int flags); + +private: + Mutex mLock; + sp<IPermissionController> mService; + + sp<IPermissionController> getService(); +}; + + +}; // namespace android +// --------------------------------------------------------------------------- +#endif // ANDROID_PERMISSION_CONTROLLER_H diff --git a/libs/sensor/ISensorServer.cpp b/libs/sensor/ISensorServer.cpp index efbbf7d826..5200545a53 100644 --- a/libs/sensor/ISensorServer.cpp +++ b/libs/sensor/ISensorServer.cpp @@ -27,6 +27,7 @@ #include <binder/Parcel.h> #include <binder/IInterface.h> +#include <binder/IResultReceiver.h> #include <sensor/Sensor.h> #include <sensor/ISensorEventConnection.h> @@ -227,6 +228,30 @@ status_t BnSensorServer::onTransact( reply->writeInt32(ret); return NO_ERROR; } + case SHELL_COMMAND_TRANSACTION: { + int in = data.readFileDescriptor(); + int out = data.readFileDescriptor(); + int err = data.readFileDescriptor(); + int argc = data.readInt32(); + Vector<String16> args; + for (int i = 0; i < argc && data.dataAvail() > 0; i++) { + args.add(data.readString16()); + } + sp<IBinder> unusedCallback; + sp<IResultReceiver> resultReceiver; + status_t status; + if ((status = data.readNullableStrongBinder(&unusedCallback)) != NO_ERROR) { + return status; + } + if ((status = data.readNullableStrongBinder(&resultReceiver)) != NO_ERROR) { + return status; + } + status = shellCommand(in, out, err, args); + if (resultReceiver != nullptr) { + resultReceiver->send(status); + } + return NO_ERROR; + } } return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/sensor/include/sensor/ISensorServer.h b/libs/sensor/include/sensor/ISensorServer.h index edf3e0f4cf..402678f0fd 100644 --- a/libs/sensor/include/sensor/ISensorServer.h +++ b/libs/sensor/include/sensor/ISensorServer.h @@ -60,6 +60,9 @@ public: class BnSensorServer : public BnInterface<ISensorServer> { public: + virtual status_t shellCommand(int in, int out, int err, + Vector<String16>& args) = 0; + virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp index 0a05dd1b18..956844f426 100644 --- a/services/sensorservice/SensorEventConnection.cpp +++ b/services/sensorservice/SensorEventConnection.cpp @@ -29,11 +29,11 @@ namespace android { SensorService::SensorEventConnection::SensorEventConnection( const sp<SensorService>& service, uid_t uid, String8 packageName, bool isDataInjectionMode, - const String16& opPackageName) + const String16& opPackageName, bool hasSensorAccess) : mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false), mDead(false), mDataInjectionMode(isDataInjectionMode), mEventCache(NULL), mCacheSize(0), mMaxCacheSize(0), mPackageName(packageName), mOpPackageName(opPackageName), - mDestroyed(false) { + mDestroyed(false), mHasSensorAccess(hasSensorAccess) { mChannel = new BitTube(mService->mSocketBufferSize); #if DEBUG_CONNECTIONS mEventsReceived = mEventsSentFromCache = mEventsSent = 0; @@ -223,6 +223,9 @@ status_t SensorService::SensorEventConnection::sendEvents( sensors_event_t* scratch, wp<const SensorEventConnection> const * mapFlushEventsToConnections) { // filter out events not for this connection + + sensors_event_t* sanitizedBuffer = nullptr; + int count = 0; Mutex::Autolock _l(mConnectionLock); if (scratch) { @@ -273,24 +276,36 @@ status_t SensorService::SensorEventConnection::sendEvents( if (mapFlushEventsToConnections[i] == this) { scratch[count++] = buffer[i]; } - ++i; } else { // Regular sensor event, just copy it to the scratch buffer. - scratch[count++] = buffer[i++]; + if (mHasSensorAccess) { + scratch[count++] = buffer[i]; + } } + i++; } while ((i<numEvents) && ((buffer[i].sensor == sensor_handle && buffer[i].type != SENSOR_TYPE_META_DATA) || (buffer[i].type == SENSOR_TYPE_META_DATA && buffer[i].meta_data.sensor == sensor_handle))); } } else { - scratch = const_cast<sensors_event_t *>(buffer); - count = numEvents; + if (mHasSensorAccess) { + scratch = const_cast<sensors_event_t *>(buffer); + count = numEvents; + } else { + scratch = sanitizedBuffer = new sensors_event_t[numEvents]; + for (size_t i = 0; i < numEvents; i++) { + if (buffer[i].type == SENSOR_TYPE_META_DATA) { + scratch[count++] = buffer[i++]; + } + } + } } sendPendingFlushEventsLocked(); // Early return if there are no events for this connection. if (count == 0) { + delete sanitizedBuffer; return status_t(NO_ERROR); } @@ -308,6 +323,7 @@ status_t SensorService::SensorEventConnection::sendEvents( // the max cache size that is desired. if (mCacheSize + count < computeMaxCacheSizeLocked()) { reAllocateCacheLocked(scratch, count); + delete sanitizedBuffer; return status_t(NO_ERROR); } // Some events need to be dropped. @@ -326,16 +342,20 @@ status_t SensorService::SensorEventConnection::sendEvents( memcpy(&mEventCache[mCacheSize - numEventsDropped], scratch + remaningCacheSize, numEventsDropped * sizeof(sensors_event_t)); } + delete sanitizedBuffer; return status_t(NO_ERROR); } - int 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; - ++mWakeLockRefCount; + int index_wake_up_event = -1; + if (mHasSensorAccess) { + 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; + ++mWakeLockRefCount; #if DEBUG_CONNECTIONS - ++mTotalAcksNeeded; + ++mTotalAcksNeeded; #endif + } } // NOTE: ASensorEvent and sensors_event_t are the same type. @@ -364,6 +384,7 @@ status_t SensorService::SensorEventConnection::sendEvents( // Add this file descriptor to the looper to get a callback when this fd is available for // writing. updateLooperRegistrationLocked(mService->getLooper()); + delete sanitizedBuffer; return size; } @@ -373,9 +394,15 @@ status_t SensorService::SensorEventConnection::sendEvents( } #endif + delete sanitizedBuffer; return size < 0 ? status_t(size) : status_t(NO_ERROR); } +void SensorService::SensorEventConnection::setSensorAccess(const bool hasAccess) { + Mutex::Autolock _l(mConnectionLock); + mHasSensorAccess = hasAccess; +} + void SensorService::SensorEventConnection::reAllocateCacheLocked(sensors_event_t const* scratch, int count) { sensors_event_t *eventCache_new; @@ -437,15 +464,18 @@ void SensorService::SensorEventConnection::writeToSocketFromCache() { sendPendingFlushEventsLocked(); for (int numEventsSent = 0; numEventsSent < mCacheSize;) { const int numEventsToWrite = helpers::min(mCacheSize - numEventsSent, maxWriteSize); - int index_wake_up_event = - findWakeUpSensorEventLocked(mEventCache + numEventsSent, numEventsToWrite); - if (index_wake_up_event >= 0) { - mEventCache[index_wake_up_event + numEventsSent].flags |= - WAKE_UP_SENSOR_EVENT_NEEDS_ACK; - ++mWakeLockRefCount; + int index_wake_up_event = -1; + if (mHasSensorAccess) { + index_wake_up_event = + findWakeUpSensorEventLocked(mEventCache + numEventsSent, numEventsToWrite); + if (index_wake_up_event >= 0) { + mEventCache[index_wake_up_event + numEventsSent].flags |= + WAKE_UP_SENSOR_EVENT_NEEDS_ACK; + ++mWakeLockRefCount; #if DEBUG_CONNECTIONS - ++mTotalAcksNeeded; + ++mTotalAcksNeeded; #endif + } } ssize_t size = SensorEventQueue::write(mChannel, diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h index 6f282cdc60..032721ea39 100644 --- a/services/sensorservice/SensorEventConnection.h +++ b/services/sensorservice/SensorEventConnection.h @@ -49,7 +49,8 @@ class SensorService::SensorEventConnection: public: SensorEventConnection(const sp<SensorService>& service, uid_t uid, String8 packageName, - bool isDataInjectionMode, const String16& opPackageName); + bool isDataInjectionMode, const String16& opPackageName, + bool hasSensorAccess); status_t sendEvents(sensors_event_t const* buffer, size_t count, sensors_event_t* scratch, wp<const SensorEventConnection> const * mapFlushEventsToConnections = NULL); @@ -66,6 +67,8 @@ public: uid_t getUid() const { return mUid; } + void setSensorAccess(const bool hasAccess); + private: virtual ~SensorEventConnection(); virtual void onFirstRef(); @@ -167,6 +170,7 @@ private: mutable Mutex mDestroyLock; bool mDestroyed; + bool mHasSensorAccess; }; } // namepsace android diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index dc491d97c0..c32ffb9c41 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -13,11 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include <binder/ActivityManager.h> #include <binder/AppOpsManager.h> #include <binder/BinderService.h> #include <binder/IServiceManager.h> #include <binder/PermissionCache.h> +#include <binder/PermissionController.h> #include <cutils/ashmem.h> +#include <cutils/misc.h> #include <cutils/properties.h> #include <hardware/sensors.h> #include <hardware_legacy/power.h> @@ -52,6 +55,8 @@ #include <sys/types.h> #include <unistd.h> +#include <private/android_filesystem_config.h> + namespace android { // --------------------------------------------------------------------------- @@ -75,6 +80,7 @@ bool SensorService::sHmacGlobalKeyIsValid = false; // Permissions. static const String16 sDumpPermission("android.permission.DUMP"); static const String16 sLocationHardwarePermission("android.permission.LOCATION_HARDWARE"); +static const String16 sManageSensorsPermission("android.permission.MANAGE_SENSORS"); SensorService::SensorService() : mInitCheck(NO_INIT), mSocketBufferSize(SOCKET_BUFFER_SIZE_NON_BATCHED), @@ -274,6 +280,23 @@ void SensorService::onFirstRef() { // priority can only be changed after run enableSchedFifoMode(); + + // Start watching UID changes to apply policy. + mUidPolicy = new UidPolicy(this); + mUidPolicy->registerSelf(); + } + } +} + +void SensorService::setSensorAccess(uid_t uid, bool hasAccess) { + SortedVector< sp<SensorEventConnection> > activeConnections; + populateActiveConnections(&activeConnections); + { + Mutex::Autolock _l(mLock); + for (size_t i = 0 ; i < activeConnections.size(); i++) { + if (activeConnections[i] != 0 && activeConnections[i]->getUid() == uid) { + activeConnections[i]->setSensorAccess(hasAccess); + } } } } @@ -312,6 +335,7 @@ SensorService::~SensorService() { for (auto && entry : mRecentEvent) { delete entry.second; } + mUidPolicy->unregisterSelf(); } status_t SensorService::dump(int fd, const Vector<String16>& args) { @@ -488,6 +512,82 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) { return NO_ERROR; } +// 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)) { + return PERMISSION_DENIED; + } + if (in == BAD_TYPE || out == BAD_TYPE || err == BAD_TYPE) { + return BAD_VALUE; + } + if (args.size() == 3 && args[0] == String16("set-uid-state")) { + return handleSetUidState(args, err); + } else if (args.size() == 2 && args[0] == String16("reset-uid-state")) { + return handleResetUidState(args, err); + } else if (args.size() == 2 && args[0] == String16("get-uid-state")) { + return handleGetUidState(args, out, err); + } else if (args.size() == 1 && args[0] == String16("help")) { + printHelp(out); + return NO_ERROR; + } + printHelp(err); + return BAD_VALUE; +} + +status_t SensorService::handleSetUidState(Vector<String16>& args, int err) { + PermissionController pc; + int uid = pc.getPackageUid(args[1], 0); + if (uid <= 0) { + ALOGE("Unknown package: '%s'", String8(args[1]).string()); + dprintf(err, "Unknown package: '%s'\n", String8(args[1]).string()); + return BAD_VALUE; + } + bool active = false; + if (args[2] == String16("active")) { + active = true; + } else if ((args[2] != String16("idle"))) { + ALOGE("Expected active or idle but got: '%s'", String8(args[2]).string()); + return BAD_VALUE; + } + mUidPolicy->addOverrideUid(uid, active); + return NO_ERROR; +} + +status_t SensorService::handleResetUidState(Vector<String16>& args, int err) { + PermissionController pc; + int uid = pc.getPackageUid(args[1], 0); + if (uid < 0) { + ALOGE("Unknown package: '%s'", String8(args[1]).string()); + dprintf(err, "Unknown package: '%s'\n", String8(args[1]).string()); + return BAD_VALUE; + } + mUidPolicy->removeOverrideUid(uid); + return NO_ERROR; +} + +status_t SensorService::handleGetUidState(Vector<String16>& args, int out, int err) { + PermissionController pc; + int uid = pc.getPackageUid(args[1], 0); + if (uid < 0) { + ALOGE("Unknown package: '%s'", String8(args[1]).string()); + dprintf(err, "Unknown package: '%s'\n", String8(args[1]).string()); + return BAD_VALUE; + } + if (mUidPolicy->isUidActive(uid)) { + return dprintf(out, "active\n"); + } else { + return dprintf(out, "idle\n"); + } +} + +status_t SensorService::printHelp(int out) { + return dprintf(out, "Sensor service commands:\n" + " get-uid-state <PACKAGE> gets the uid state\n" + " set-uid-state <PACKAGE> <active|idle> overrides the uid state\n" + " reset-uid-state <PACKAGE> clears the uid state override\n" + " help print this message\n"); +} + //TODO: move to SensorEventConnection later void SensorService::cleanupAutoDisabledSensorLocked(const sp<SensorEventConnection>& connection, sensors_event_t const* buffer, const int count) { @@ -677,7 +777,6 @@ bool SensorService::threadLoop() { } } - // Send our events to clients. Check the state of wake lock for each client and release the // lock if none of the clients need it. bool needsWakeLock = false; @@ -939,8 +1038,9 @@ 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)); + requestedMode == DATA_INJECTION, connOpPackageName, hasSensorAccess)); if (requestedMode == DATA_INJECTION) { if (mActiveConnections.indexOf(result) < 0) { mActiveConnections.add(result); @@ -1530,4 +1630,98 @@ bool SensorService::isOperationRestricted(const String16& opPackageName) { return false; } +void SensorService::UidPolicy::registerSelf() { + ActivityManager am; + am.registerUidObserver(this, ActivityManager::UID_OBSERVER_GONE + | ActivityManager::UID_OBSERVER_IDLE + | ActivityManager::UID_OBSERVER_ACTIVE, + ActivityManager::PROCESS_STATE_UNKNOWN, + String16("android")); +} + +void SensorService::UidPolicy::unregisterSelf() { + ActivityManager am; + am.unregisterUidObserver(this); +} + +void SensorService::UidPolicy::onUidGone(__unused uid_t uid, __unused bool disabled) { + onUidIdle(uid, disabled); +} + +void SensorService::UidPolicy::onUidActive(uid_t uid) { + { + Mutex::Autolock _l(mUidLock); + mActiveUids.insert(uid); + } + sp<SensorService> service = mService.promote(); + if (service != nullptr) { + service->setSensorAccess(uid, true); + } +} + +void SensorService::UidPolicy::onUidIdle(uid_t uid, __unused bool disabled) { + bool deleted = false; + { + Mutex::Autolock _l(mUidLock); + if (mActiveUids.erase(uid) > 0) { + deleted = true; + } + } + if (deleted) { + sp<SensorService> service = mService.promote(); + if (service != nullptr) { + service->setSensorAccess(uid, false); + } + } +} + +void SensorService::UidPolicy::addOverrideUid(uid_t uid, bool active) { + updateOverrideUid(uid, active, true); +} + +void SensorService::UidPolicy::removeOverrideUid(uid_t uid) { + updateOverrideUid(uid, false, false); +} + +void SensorService::UidPolicy::updateOverrideUid(uid_t uid, bool active, bool insert) { + bool wasActive = false; + bool isActive = false; + { + Mutex::Autolock _l(mUidLock); + wasActive = isUidActiveLocked(uid); + mOverrideUids.erase(uid); + if (insert) { + mOverrideUids.insert(std::pair<uid_t, bool>(uid, active)); + } + isActive = isUidActiveLocked(uid); + } + if (wasActive != isActive) { + sp<SensorService> service = mService.promote(); + if (service != nullptr) { + service->setSensorAccess(uid, isActive); + } + } +} + +bool SensorService::UidPolicy::isUidActive(uid_t uid) { + // Non-app UIDs are considered always active + if (uid < FIRST_APPLICATION_UID) { + return true; + } + Mutex::Autolock _l(mUidLock); + return isUidActiveLocked(uid); +} + +bool SensorService::UidPolicy::isUidActiveLocked(uid_t uid) { + // Non-app UIDs are considered always active + if (uid < FIRST_APPLICATION_UID) { + return true; + } + auto it = mOverrideUids.find(uid); + if (it != mOverrideUids.end()) { + return it->second; + } + return mActiveUids.find(uid) != mActiveUids.end(); +} + }; // namespace android diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h index 3e183942ff..f71723d8c9 100644 --- a/services/sensorservice/SensorService.h +++ b/services/sensorservice/SensorService.h @@ -21,6 +21,7 @@ #include "RecentEventLogger.h" #include <binder/BinderService.h> +#include <binder/IUidObserver.h> #include <cutils/compiler.h> #include <sensor/ISensorServer.h> #include <sensor/ISensorEventConnection.h> @@ -85,6 +86,9 @@ public: status_t flushSensor(const sp<SensorEventConnection>& connection, const String16& opPackageName); + + virtual status_t shellCommand(int in, int out, int err, Vector<String16>& args); + private: friend class BinderService<SensorService>; @@ -93,6 +97,40 @@ private: class SensorEventAckReceiver; class SensorRegistrationInfo; + // If accessing a sensor we need to make sure the UID has access to it. If + // the app UID is idle then it cannot access sensors and gets no trigger + // events, no on-change events, flush event behavior does not change, and + // recurring events are the same as the first one delivered in idle state + // emulating no sensor change. As soon as the app UID transitions to an + // active state we will start reporting events as usual and vise versa. This + // approach transparently handles observing sensors while the app UID transitions + // between idle/active state avoiding to get stuck in a state receiving sensor + // data while idle or not receiving sensor data while active. + class UidPolicy : public BnUidObserver { + public: + explicit UidPolicy(wp<SensorService> service) + : mService(service) {} + void registerSelf(); + void unregisterSelf(); + + bool isUidActive(uid_t uid); + + void onUidGone(uid_t uid, bool disabled); + void onUidActive(uid_t uid); + void onUidIdle(uid_t uid, bool disabled); + + void addOverrideUid(uid_t uid, bool active); + void removeOverrideUid(uid_t uid); + private: + bool isUidActiveLocked(uid_t uid); + void updateOverrideUid(uid_t uid, bool active, bool insert); + + Mutex mUidLock; + wp<SensorService> mService; + std::unordered_set<uid_t> mActiveUids; + std::unordered_map<uid_t, bool> mOverrideUids; + }; + enum Mode { // The regular operating mode where any application can register/unregister/call flush on // sensors. @@ -161,7 +199,6 @@ private: virtual int setOperationParameter( int32_t handle, int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints); virtual status_t dump(int fd, const Vector<String16>& args); - String8 getSensorName(int handle) const; bool isVirtualSensor(int handle) const; sp<SensorInterface> getSensorInterfaceFromHandle(int handle) const; @@ -225,6 +262,18 @@ private: // Enable SCHED_FIFO priority for thread void enableSchedFifoMode(); + // Sets whether the given UID can get sensor data + void setSensorAccess(uid_t uid, bool hasAccess); + + // Overrides the UID state as if it is idle + status_t handleSetUidState(Vector<String16>& args, int err); + // Clears the override for the UID state + status_t handleResetUidState(Vector<String16>& args, int err); + // Gets the UID state + status_t handleGetUidState(Vector<String16>& args, int out, int err); + // Prints the shell command help + status_t printHelp(int out); + static uint8_t sHmacGlobalKey[128]; static bool sHmacGlobalKeyIsValid; @@ -257,6 +306,8 @@ private: int mNextSensorRegIndex; Vector<SensorRegistrationInfo> mLastNSensorRegistrations; + + sp<UidPolicy> mUidPolicy; }; } // namespace android |