Support restricted mode in SensorService.

In restricted mode, only CTS tests can register for sensors or call flush() on them. The requests
from other applications will be ignored.

Change-Id: Ieb923df3e0cfe3390fe2d052af776da79589744b
This commit is contained in:
Aravind Akella 2015-02-11 15:54:35 -08:00
parent 5b20fd0882
commit 4949c50372
8 changed files with 210 additions and 36 deletions

View File

@ -30,6 +30,7 @@ namespace android {
class Sensor;
class ISensorEventConnection;
class String8;
class ISensorServer : public IInterface
{
@ -37,7 +38,7 @@ public:
DECLARE_META_INTERFACE(SensorServer);
virtual Vector<Sensor> getSensorList() = 0;
virtual sp<ISensorEventConnection> createSensorEventConnection() = 0;
virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName) = 0;
};
// ----------------------------------------------------------------------------

View File

@ -40,7 +40,7 @@ namespace android {
class ISensorServer;
class Sensor;
class SensorEventQueue;
class String8;
// ----------------------------------------------------------------------------
class SensorManager :
@ -53,7 +53,7 @@ public:
ssize_t getSensorList(Sensor const* const** list) const;
Sensor const* getDefaultSensor(int type);
sp<SensorEventQueue> createEventQueue();
sp<SensorEventQueue> createEventQueue(String8 packageName = String8(""));
private:
// DeathRecipient interface

View File

@ -63,10 +63,11 @@ public:
return v;
}
virtual sp<ISensorEventConnection> createSensorEventConnection()
virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName)
{
Parcel data, reply;
data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
data.writeString8(packageName);
remote()->transact(CREATE_SENSOR_EVENT_CONNECTION, data, &reply);
return interface_cast<ISensorEventConnection>(reply.readStrongBinder());
}
@ -96,7 +97,8 @@ status_t BnSensorServer::onTransact(
}
case CREATE_SENSOR_EVENT_CONNECTION: {
CHECK_INTERFACE(ISensorServer, data, reply);
sp<ISensorEventConnection> connection(createSensorEventConnection());
String8 packageName = data.readString8();
sp<ISensorEventConnection> connection(createSensorEventConnection(packageName));
reply->writeStrongBinder(IInterface::asBinder(connection));
return NO_ERROR;
}

View File

@ -139,14 +139,14 @@ Sensor const* SensorManager::getDefaultSensor(int type)
return NULL;
}
sp<SensorEventQueue> SensorManager::createEventQueue()
sp<SensorEventQueue> SensorManager::createEventQueue(String8 packageName)
{
sp<SensorEventQueue> queue;
Mutex::Autolock _l(mLock);
while (assertStateLocked() == NO_ERROR) {
sp<ISensorEventConnection> connection =
mSensorServer->createSensorEventConnection();
mSensorServer->createSensorEventConnection(packageName);
if (connection == NULL) {
// SensorService just died.
ALOGE("createEventQueue: connection is NULL. SensorService died.");

View File

@ -85,6 +85,7 @@ void SensorDevice::dump(String8& result)
Mutex::Autolock _l(mLock);
for (size_t i=0 ; i<size_t(count) ; i++) {
const Info& info = mActivationCount.valueFor(list[i].handle);
if (info.batchParams.isEmpty()) continue;
result.appendFormat("handle=0x%08x, active-count=%zu, batch_period(ms)={ ", list[i].handle,
info.batchParams.size());
for (size_t j = 0; j < info.batchParams.size(); j++) {
@ -147,8 +148,12 @@ status_t SensorDevice::activate(void* ident, int handle, int enabled)
if (enabled) {
ALOGD_IF(DEBUG_CONNECTIONS, "enable index=%zd", info.batchParams.indexOfKey(ident));
if (isClientDisabledLocked(ident)) {
return INVALID_OPERATION;
}
if (info.batchParams.indexOfKey(ident) >= 0) {
if (info.batchParams.size() == 1) {
if (info.numActiveClients() == 1) {
// This is the first connection, we need to activate the underlying h/w sensor.
actuateHardware = true;
}
@ -160,7 +165,7 @@ status_t SensorDevice::activate(void* ident, int handle, int enabled)
ALOGD_IF(DEBUG_CONNECTIONS, "disable index=%zd", info.batchParams.indexOfKey(ident));
if (info.removeBatchParamsForIdent(ident) >= 0) {
if (info.batchParams.size() == 0) {
if (info.numActiveClients() == 0) {
// This is the last connection, we need to de-activate the underlying h/w sensor.
actuateHardware = true;
} else {
@ -181,10 +186,15 @@ status_t SensorDevice::activate(void* ident, int handle, int enabled)
} else {
// sensor wasn't enabled for this ident
}
if (isClientDisabledLocked(ident)) {
return NO_ERROR;
}
}
if (actuateHardware) {
ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle, enabled);
ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
enabled);
err = mSensorDevice->activate(
reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice), handle, enabled);
ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
@ -197,7 +207,7 @@ status_t SensorDevice::activate(void* ident, int handle, int enabled)
}
// On older devices which do not support batch, call setDelay().
if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1 && info.batchParams.size() > 0) {
if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1 && info.numActiveClients() > 0) {
ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w setDelay %d %" PRId64, handle,
info.bestBatchParams.batchDelay);
mSensorDevice->setDelay(
@ -279,6 +289,7 @@ status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodN
samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
}
Mutex::Autolock _l(mLock);
if (isClientDisabledLocked(ident)) return INVALID_OPERATION;
Info& info( mActivationCount.editValueFor(handle) );
// If the underlying sensor is NOT in continuous mode, setDelay() should return an error.
// Calling setDelay() in batch mode is an invalid operation.
@ -298,7 +309,6 @@ status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodN
int SensorDevice::getHalDeviceVersion() const {
if (!mSensorDevice) return -1;
return mSensorDevice->common.version;
}
@ -306,12 +316,89 @@ status_t SensorDevice::flush(void* ident, int handle) {
if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1) {
return INVALID_OPERATION;
}
if (isClientDisabled(ident)) return INVALID_OPERATION;
ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
return mSensorDevice->flush(mSensorDevice, handle);
}
bool SensorDevice::isClientDisabled(void* ident) {
Mutex::Autolock _l(mLock);
return isClientDisabledLocked(ident);
}
bool SensorDevice::isClientDisabledLocked(void* ident) {
return mDisabledClients.indexOf(ident) >= 0;
}
void SensorDevice::enableAllSensors() {
Mutex::Autolock _l(mLock);
mDisabledClients.clear();
const int halVersion = getHalDeviceVersion();
for (size_t i = 0; i< mActivationCount.size(); ++i) {
Info& info = mActivationCount.editValueAt(i);
if (info.batchParams.isEmpty()) continue;
info.selectBatchParams();
const int sensor_handle = mActivationCount.keyAt(i);
ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ",
sensor_handle);
status_t err(NO_ERROR);
if (halVersion > SENSORS_DEVICE_API_VERSION_1_0) {
err = mSensorDevice->batch(mSensorDevice, sensor_handle,
info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
info.bestBatchParams.batchTimeout);
ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
}
if (err == NO_ERROR) {
err = mSensorDevice->activate(
reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
sensor_handle, 1);
ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
}
if (halVersion <= SENSORS_DEVICE_API_VERSION_1_0) {
err = mSensorDevice->setDelay(
reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
sensor_handle, info.bestBatchParams.batchDelay);
ALOGE_IF(err, "Error calling setDelay sensor %d (%s)", sensor_handle, strerror(-err));
}
}
}
void SensorDevice::disableAllSensors() {
Mutex::Autolock _l(mLock);
for (size_t i = 0; i< mActivationCount.size(); ++i) {
const Info& info = mActivationCount.valueAt(i);
// Check if this sensor has been activated previously and disable it.
if (info.batchParams.size() > 0) {
const int sensor_handle = mActivationCount.keyAt(i);
ALOGD_IF(DEBUG_CONNECTIONS, "\t>> actuating h/w sensor disable handle=%d ",
sensor_handle);
mSensorDevice->activate(
reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice),
sensor_handle, 0);
// Add all the connections that were registered for this sensor to the disabled
// clients list.
for (int j = 0; j < info.batchParams.size(); ++j) {
mDisabledClients.add(info.batchParams.keyAt(j));
}
}
}
}
// ---------------------------------------------------------------------------
int SensorDevice::Info::numActiveClients() {
SensorDevice& device(SensorDevice::getInstance());
int num = 0;
for (size_t i = 0; i < batchParams.size(); ++i) {
if (!device.isClientDisabledLocked(batchParams.keyAt(i))) {
++num;
}
}
return num;
}
status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int flags,
int64_t samplingPeriodNs,
int64_t maxBatchReportLatencyNs) {
@ -329,19 +416,16 @@ status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int flags,
}
void SensorDevice::Info::selectBatchParams() {
BatchParams bestParams(-1, -1, -1);
BatchParams bestParams(0, -1, -1);
SensorDevice& device(SensorDevice::getInstance());
if (batchParams.size() > 0) {
BatchParams params = batchParams.valueAt(0);
bestParams = params;
}
for (size_t i = 1; i < batchParams.size(); ++i) {
for (size_t i = 0; i < batchParams.size(); ++i) {
if (device.isClientDisabledLocked(batchParams.keyAt(i))) continue;
BatchParams params = batchParams.valueAt(i);
if (params.batchDelay < bestParams.batchDelay) {
if (bestParams.batchDelay == -1 || params.batchDelay < bestParams.batchDelay) {
bestParams.batchDelay = params.batchDelay;
}
if (params.batchTimeout < bestParams.batchTimeout) {
if (bestParams.batchTimeout == -1 || params.batchTimeout < bestParams.batchTimeout) {
bestParams.batchTimeout = params.batchTimeout;
}
}

View File

@ -42,6 +42,7 @@ class SensorDevice : public Singleton<SensorDevice> {
// Struct to store all the parameters(samplingPeriod, maxBatchReportLatency and flags) from
// batch call. For continous mode clients, maxBatchReportLatency is set to zero.
struct BatchParams {
// TODO: Get rid of flags parameter everywhere.
int flags;
nsecs_t batchDelay, batchTimeout;
BatchParams() : flags(0), batchDelay(0), batchTimeout(0) {}
@ -65,7 +66,7 @@ class SensorDevice : public Singleton<SensorDevice> {
// requested by the client.
KeyedVector<void*, BatchParams> batchParams;
Info() : bestBatchParams(-1, -1, -1) {}
Info() : bestBatchParams(0, -1, -1) {}
// Sets batch parameters for this ident. Returns error if this ident is not already present
// in the KeyedVector above.
status_t setBatchParamsForIdent(void* ident, int flags, int64_t samplingPeriodNs,
@ -75,10 +76,17 @@ class SensorDevice : public Singleton<SensorDevice> {
// Removes batchParams for an ident and re-computes bestBatchParams. Returns the index of
// the removed ident. If index >=0, ident is present and successfully removed.
ssize_t removeBatchParamsForIdent(void* ident);
int numActiveClients();
};
DefaultKeyedVector<int, Info> mActivationCount;
// Use this vector to determine which client is activated or deactivated.
SortedVector<void *> mDisabledClients;
SensorDevice();
bool isClientDisabled(void* ident);
bool isClientDisabledLocked(void* ident);
public:
ssize_t getSensorList(sensor_t const** list);
status_t initCheck() const;
@ -90,6 +98,8 @@ public:
// Call batch with timeout zero instead of calling setDelay() for newer devices.
status_t setDelay(void* ident, int handle, int64_t ns);
status_t flush(void* ident, int handle);
void disableAllSensors();
void enableAllSensors();
void autoDisable(void *ident, int handle);
void dump(String8& result);
};

View File

@ -190,6 +190,7 @@ void SensorService::onFirstRef()
mSensorEventBuffer = new sensors_event_t[minBufferSize];
mSensorEventScratch = new sensors_event_t[minBufferSize];
mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];
mMode = NORMAL;
mAckReceiver = new SensorEventAckReceiver(this);
mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
@ -230,7 +231,7 @@ SensorService::~SensorService()
static const String16 sDump("android.permission.DUMP");
status_t SensorService::dump(int fd, const Vector<String16>& /*args*/)
status_t SensorService::dump(int fd, const Vector<String16>& args)
{
String8 result;
if (!PermissionCache::checkCallingPermission(sDump)) {
@ -238,6 +239,26 @@ status_t SensorService::dump(int fd, const Vector<String16>& /*args*/)
"can't dump SensorService from pid=%d, uid=%d\n",
IPCThreadState::self()->getCallingPid(),
IPCThreadState::self()->getCallingUid());
} else if (args.size() > 0) {
if (args.size() > 1) {
return INVALID_OPERATION;
}
Mutex::Autolock _l(mLock);
SensorDevice& dev(SensorDevice::getInstance());
if (args[0] == String16("restrict") && mMode == NORMAL) {
mMode = RESTRICTED;
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();
}
} else if (args[0] == String16("enable") && mMode == RESTRICTED) {
mMode = NORMAL;
dev.enableAllSensors();
}
return status_t(NO_ERROR);
} else {
Mutex::Autolock _l(mLock);
result.append("Sensor List:\n");
@ -341,6 +362,17 @@ status_t SensorService::dump(int fd, const Vector<String16>& /*args*/)
result.appendFormat("Socket Buffer size = %d events\n",
mSocketBufferSize/sizeof(sensors_event_t));
result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" : "not held");
result.appendFormat("Mode :");
switch(mMode) {
case NORMAL:
result.appendFormat(" NORMAL\n");
break;
case RESTRICTED:
result.appendFormat(" RESTRICTED\n");
break;
case DATA_INJECTION:
result.appendFormat(" DATA_INJECTION\n");
}
result.appendFormat("%zd active connections\n", mActiveConnections.size());
for (size_t i=0 ; i < mActiveConnections.size() ; i++) {
@ -554,7 +586,6 @@ void SensorService::setWakeLockAcquiredLocked(bool acquire) {
}
}
bool SensorService::isWakeLockAcquired() {
Mutex::Autolock _l(mLock);
return mWakeLockAcquired;
@ -630,7 +661,6 @@ bool SensorService::isWakeUpSensorEvent(const sensors_event_t& event) const {
return sensor != NULL && sensor->getSensor().isWakeUpSensor();
}
SensorService::SensorRecord * SensorService::getSensorRecord(int handle) {
return mActiveSensors.valueFor(handle);
}
@ -655,10 +685,10 @@ Vector<Sensor> SensorService::getSensorList()
return accessibleSensorList;
}
sp<ISensorEventConnection> SensorService::createSensorEventConnection()
sp<ISensorEventConnection> SensorService::createSensorEventConnection(const String8& packageName)
{
uid_t uid = IPCThreadState::self()->getCallingUid();
sp<SensorEventConnection> result(new SensorEventConnection(this, uid));
sp<SensorEventConnection> result(new SensorEventConnection(this, uid, packageName));
return result;
}
@ -708,7 +738,7 @@ Sensor SensorService::getSensorFromHandle(int handle) const {
}
status_t SensorService::enable(const sp<SensorEventConnection>& connection,
int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags)
int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags)
{
if (mInitCheck != NO_ERROR)
return mInitCheck;
@ -723,6 +753,10 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection,
}
Mutex::Autolock _l(mLock);
if (mMode == RESTRICTED && !isWhiteListedPackage(connection->getPackageName())) {
return INVALID_OPERATION;
}
SensorRecord* rec = mActiveSensors.valueFor(handle);
if (rec == 0) {
rec = new SensorRecord(connection);
@ -773,7 +807,7 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection,
"rate=%" PRId64 " timeout== %" PRId64"",
handle, reservedFlags, samplingPeriodNs, maxBatchReportLatencyNs);
status_t err = sensor->batch(connection.get(), handle, reservedFlags, samplingPeriodNs,
status_t err = sensor->batch(connection.get(), handle, 0, samplingPeriodNs,
maxBatchReportLatencyNs);
// Call flush() before calling activate() on the sensor. Wait for a first flush complete
@ -969,6 +1003,11 @@ void SensorService::populateActiveConnections(
}
}
bool SensorService::isWhiteListedPackage(const String8& packageName) {
// TODO: Come up with a list of packages.
return (packageName.find(".cts.") != -1);
}
// ---------------------------------------------------------------------------
SensorService::SensorRecord::SensorRecord(
const sp<SensorEventConnection>& connection)
@ -1025,12 +1064,16 @@ SensorService::SensorRecord::getFirstPendingFlushConnection() {
return NULL;
}
void SensorService::SensorRecord::clearAllPendingFlushConnections() {
mPendingFlushConnections.clear();
}
// ---------------------------------------------------------------------------
SensorService::SensorEventConnection::SensorEventConnection(
const sp<SensorService>& service, uid_t uid)
const sp<SensorService>& service, uid_t uid, String8 packageName)
: mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false),
mDead(false), mEventCache(NULL), mCacheSize(0), mMaxCacheSize(0) {
mDead(false), mEventCache(NULL), mCacheSize(0), mMaxCacheSize(0), mPackageName(packageName) {
mChannel = new BitTube(mService->mSocketBufferSize);
#if DEBUG_CONNECTIONS
mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
@ -1062,8 +1105,8 @@ void SensorService::SensorEventConnection::resetWakeLockRefCount() {
void SensorService::SensorEventConnection::dump(String8& result) {
Mutex::Autolock _l(mConnectionLock);
result.appendFormat("\t WakeLockRefCount %d | uid %d | cache size %d | max cache size %d\n",
mWakeLockRefCount, mUid, mCacheSize, mMaxCacheSize);
result.appendFormat("\t%s | WakeLockRefCount %d | uid %d | cache size %d | max cache size %d\n",
mPackageName.string(), mWakeLockRefCount, mUid, mCacheSize, mMaxCacheSize);
for (size_t i = 0; i < mSensorInfo.size(); ++i) {
const FlushInfo& flushInfo = mSensorInfo.valueAt(i);
result.appendFormat("\t %s 0x%08x | status: %s | pending flush events %d \n",
@ -1126,6 +1169,10 @@ bool SensorService::SensorEventConnection::hasOneShotSensors() const {
return false;
}
String8 SensorService::SensorEventConnection::getPackageName() const {
return mPackageName;
}
void SensorService::SensorEventConnection::setFirstFlushPending(int32_t handle,
bool value) {
Mutex::Autolock _l(mConnectionLock);

View File

@ -27,6 +27,7 @@
#include <utils/AndroidThreads.h>
#include <utils/RefBase.h>
#include <utils/Looper.h>
#include <utils/String8.h>
#include <binder/BinderService.h>
@ -65,6 +66,27 @@ class SensorService :
{
friend class BinderService<SensorService>;
enum Mode {
// The regular operating mode where any application can register/unregister/call flush on
// sensors.
NORMAL = 0,
// This mode is used only for testing sensors. Each sensor can be tested in isolation with
// the required sampling_rate and maxReportLatency parameters without having to think about
// the data rates requested by other applications. End user devices are always expected to be
// in NORMAL mode. When this mode is first activated, all active sensors from all connections
// are disabled. Calling flush() will return an error. In this mode, only the requests from
// selected apps whose package names are whitelisted are allowed (typically CTS apps). Only
// these apps can register/unregister/call flush() on sensors. If SensorService switches to
// NORMAL mode again, all sensors that were previously registered to are activated with the
// corresponding paramaters if the application hasn't unregistered for sensors in the mean
// time.
// NOTE: Non whitelisted app whose sensors were previously deactivated may still receive
// events if a whitelisted app requests data from the same sensor.
RESTRICTED,
// TODO: This mode hasn't been implemented yet.
DATA_INJECTION
};
static const char* WAKE_LOCK_NAME;
static char const* getServiceName() ANDROID_API { return "sensorservice"; }
@ -78,7 +100,7 @@ class SensorService :
// ISensorServer interface
virtual Vector<Sensor> getSensorList();
virtual sp<ISensorEventConnection> createSensorEventConnection();
virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName);
virtual status_t dump(int fd, const Vector<String16>& args);
class SensorEventConnection : public BnSensorEventConnection, public LooperCallback {
@ -133,7 +155,6 @@ class SensorService :
// connection FD may be added to the Looper. The flags to set are determined by the internal
// state of the connection. FDs are added to the looper when wake-up sensors are registered
// (to poll for acknowledgements) and when write fails on the socket when there are too many
// events (to poll when the FD is available for writing). FDs are removed when there is an
// error and the other end hangs up or when this client unregisters for this connection.
void updateLooperRegistration(const sp<Looper>& looper);
void updateLooperRegistrationLocked(const sp<Looper>& looper);
@ -169,6 +190,7 @@ class SensorService :
KeyedVector<int, FlushInfo> mSensorInfo;
sensors_event_t *mEventCache;
int mCacheSize, mMaxCacheSize;
String8 mPackageName;
#if DEBUG_CONNECTIONS
int mEventsReceived, mEventsSent, mEventsSentFromCache;
@ -176,7 +198,7 @@ class SensorService :
#endif
public:
SensorEventConnection(const sp<SensorService>& service, uid_t uid);
SensorEventConnection(const sp<SensorService>& service, uid_t uid, String8 packageName);
status_t sendEvents(sensors_event_t const* buffer, size_t count,
sensors_event_t* scratch,
@ -190,6 +212,7 @@ class SensorService :
void dump(String8& result);
bool needsWakeLock();
void resetWakeLockRefCount();
String8 getPackageName() const;
uid_t getUid() const { return mUid; }
};
@ -208,6 +231,7 @@ class SensorService :
void addPendingFlushConnection(const sp<SensorEventConnection>& connection);
void removeFirstPendingFlushConnection();
SensorEventConnection * getFirstPendingFlushConnection();
void clearAllPendingFlushConnections();
};
class SensorEventAckReceiver : public Thread {
@ -261,6 +285,11 @@ class SensorService :
// to the output vector.
void populateActiveConnections(SortedVector< sp<SensorEventConnection> >* activeConnections);
// If SensorService is operating in RESTRICTED mode, only select whitelisted packages are
// allowed to register for or call flush on sensors. Typically only cts test packages are
// allowed.
bool isWhiteListedPackage(const String8& packageName);
// constants
Vector<Sensor> mSensorList;
Vector<Sensor> mUserSensorListDebug;
@ -282,6 +311,7 @@ class SensorService :
bool mWakeLockAcquired;
sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
SensorEventConnection const **mMapFlushEventsToConnections;
Mode mMode;
// The size of this vector is constant, only the items are mutable
KeyedVector<int32_t, sensors_event_t> mLastEventSeen;