framework是android的核心架构,主要对JAVA提供相应的接口。sensor部分上节中说了几个接口,我们跟进下去学习下。
localSensorManager.registerListener(this,localSensor, 3);
step 1:
\frameworks\base\core\java\android\hardware\SensorManager.java
public boolean registerListener(SensorListener listener, int sensors,int rate) {
return getLegacySensorManager().registerListener(listener,sensors, rate);
}
step 2:
frameworks\base\core\java\android\hardware\LegacySensorManager.java
public boolean registerListener(SensorListener listener, int sensors,int rate) {
if (listener == null) {
return false;
}
boolean result = false;
result = registerLegacyListener(SensorManager.SENSOR_ACCELEROMETER,
Sensor.TYPE_ACCELEROMETER,listener, sensors, rate) || result;
result = registerLegacyListener(SensorManager.SENSOR_MAGNETIC_FIELD,
Sensor.TYPE_MAGNETIC_FIELD,listener, sensors, rate) || result;
result = registerLegacyListener(SensorManager.SENSOR_ORIENTATION_RAW,
Sensor.TYPE_ORIENTATION,listener, sensors, rate) || result;
result = registerLegacyListener(SensorManager.SENSOR_ORIENTATION,
Sensor.TYPE_ORIENTATION,listener, sensors, rate) || result;
result = registerLegacyListener(SensorManager.SENSOR_TEMPERATURE,
Sensor.TYPE_TEMPERATURE,listener, sensors, rate) || result;
return result;
}
step 3:
frameworks\base\core\java\android\hardware\LegacySensorManager.java
private boolean registerLegacyListener(int legacyType, int type,
SensorListener listener, int sensors, int rate) {
boolean result = false;
// Are we activating this legacy sensor?
if ((sensors & legacyType) != 0) {
// if so, find a suitable Sensor
Sensor sensor = mSensorManager.getDefaultSensor(type);
if (sensor != null) {
// We do all of this workholding the legacy listener lock to ensure
// that the invariants aroundlisteners are maintained. This is safe
// because neitherregisterLegacyListener nor unregisterLegacyListener
// are called reentrantly whilesensors are being registered or unregistered.
synchronized(mLegacyListenersMap) {
// If we don't already haveone, create a LegacyListener
// to wrap this listenerand process the events as
// they are expected bylegacy apps.
LegacyListenerlegacyListener = mLegacyListenersMap.get(listener);
if (legacyListener == null){
// we didn't find aLegacyListener for this client,
// create one, and putit in our list.
legacyListener = newLegacyListener(listener);
mLegacyListenersMap.put(listener,legacyListener);
}
// register this legacysensor with this legacy listener
if(legacyListener.registerSensor(legacyType)) {
// and finally,register the legacy listener with the new apis
/*
有回调到SensorManager中的registerListener,但是注意这次带的参数类型为:
LegacyListenerimplements SensorEventListener
SensorEventListener是个接口,里面就是对于应用层的两个方法:onSensorChanged和onAccuracyChanged
public interfaceSensorEventListener {
/**
* Called when sensor values have changed.
* <p>See {@linkandroid.hardware.SensorManager SensorManager}
* for details on possible sensor types.
* <p>See also {@linkandroid.hardware.SensorEvent SensorEvent}.
*
* <p><b>NOTE:</b> Theapplication doesn't own the
* {@link android.hardware.SensorEventevent}
* object passed as a parameter andtherefore cannot hold on to it.
* The object may be part of an internalpool and may be reused by
* the framework.
*
* @param event the {@linkandroid.hardware.SensorEvent SensorEvent}.
*/
public void onSensorChanged(SensorEventevent);
/**
* Called when the accuracy of theregistered sensor has changed.
*
* <p>See the SENSOR_STATUS_* constantsin
* {@link android.hardware.SensorManagerSensorManager} for details.
*
* @param accuracy The new accuracy of thissensor, one of
* {@code SensorManager.SENSOR_STATUS_*}
*/
public void onAccuracyCh
*/
result =mSensorManager.registerListener(legacyListener, sensor, rate);
} else {
result = true; //sensor already enabled
}
}
}
}
return result;
}
step 4:
\frameworks\base\core\java\android\hardware\SensorManager.java
public boolean registerListener(SensorEventListener listener, Sensorsensor, int samplingPeriodUs,
int maxReportLatencyUs, Handler handler) {
int delayUs = getDelay(samplingPeriodUs);
return registerListenerImpl(listener, sensor,delayUs, handler, maxReportLatencyUs, 0);
}
step 5:
\frameworks\base\core\java\android\hardware\SystemSensorManager.java
protected boolean registerListenerImpl(SensorEventListener listener,Sensor sensor,
int delayUs, Handler handler, int maxBatchReportLatencyUs, intreservedFlags) {
if (listener == null || sensor == null) {
Log.e(TAG, "sensor or listener is null");
return false;
}
// Trigger Sensors should use the requestTriggerSensor call.
if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
Log.e(TAG, "Trigger Sensors should use the requestTriggerSensor.");
return false;
}
if (maxBatchReportLatencyUs < 0 || delayUs < 0) {
Log.e(TAG, "maxBatchReportLatencyUs and delayUs should benon-negative");
return false;
}
// Invariants to preserve:
// - one Looper per SensorEventListener
// - one Looper per SensorEventQueue
// We map SensorEventListener to a SensorEventQueue, which holds thelooper
synchronized (mSensorListeners) {
SensorEventQueue queue = mSensorListeners.get(listener);
if (queue == null) {
/*
这里会给监听器创建一个进程,用来一直监听事件的发生。
*/
Looper looper = (handler !=null) ? handler.getLooper() : mMainLooper;
final String fullClassName =listener.getClass().getEnclosingClass() != null ?
listener.getClass().getEnclosingClass().getName() :
listener.getClass().getName();
/*
这里分开分析SensorEventQueue的创建和其addSensor方法。
*/
queue = new SensorEventQueue(listener, looper,this, fullClassName);
if (!queue.addSensor(sensor,delayUs, maxBatchReportLatencyUs)) {
queue.dispose();
return false;
}
mSensorListeners.put(listener,queue);
return true;
} else {
return queue.addSensor(sensor,delayUs, maxBatchReportLatencyUs);
}
}
}
SensorEventQueue的创建如下:
step 6.1.1:
\frameworks\base\core\java\android\hardware\SystemSensorManager.java
public SensorEventQueue(SensorEventListener listener, Looper looper,
SystemSensorManager manager,String packageName) {
/*
SensorEventQueue的父类为BaseEventQueue,所以调用其父类的方法,也在该文档中。
BaseEventQueue里面有很多本地方法的调用。快到本地层了。
*/
super(looper, manager, OPERATING_MODE_NORMAL,packageName);
mListener = listener;
}
STEP 6.1.2:
\frameworks\base\core\java\android\hardware\SystemSensorManager.java
BaseEventQueue(Looper looper, SystemSensorManager manager, int mode,String packageName) {
if (packageName == null) packageName = "";
nSensorEventQueue =nativeInitBaseEventQueue(manager.mNativeInstance,
new WeakReference<>(this),looper.getQueue(), mScratch,
packageName, mode,manager.mContext.getOpPackageName());
mCloseGuard.open("dispose");
mManager = manager;
}
step 6.1.3:
\frameworks\base\core\jni\android_hardware_SensorManager.cpp
static jlongnativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,
jobject eventQWeak, jobject msgQ, jfloatArray scratch, jstringpackageName, jint mode) {
SensorManager* mgr =reinterpret_cast<SensorManager*>(sensorManager);
ScopedUtfChars packageUtf(env, packageName);
String8 clientName(packageUtf.c_str());
sp<SensorEventQueue> queue(mgr->createEventQueue(clientName,mode));
sp<MessageQueue> messageQueue =android_os_MessageQueue_getMessageQueue(env, msgQ);
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is notinitialized.");
return 0;
}
sp<Receiver> receiver = newReceiver(queue, messageQueue, eventQWeak, scratch);
receiver->incStrong((void*)nativeInitSensorEventQueue);
return jlong(receiver.get());
}
step 6.1.4:
/*
Receiver创建后会自动执行onFirstRef, 在onFirstRef中,再执行mMessageQueue->getLooper()->addFd用来启动LoopCallback这句最关键了,
把channel的fd, 加到了looper的fd集合里,并且传递了this进入,本身class Receiver : public LooperCallback
就是继承LooperCallback, 所以server端的fd动作(SendEvent),都会被looper回调到Receiver的接口里, 实际
上是:Receiver::handleEvent.
*/
virtual void onFirstRef() {
LooperCallback::onFirstRef();
mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(),0,
ALOOPER_EVENT_INPUT, this,mSensorQueue.get());
}
virtual int handleEvent(int fd, int events,void* data) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
sp<SensorEventQueue> q =reinterpret_cast<SensorEventQueue *>(data);
ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env,mReceiverWeakGlobal));
ssize_t n;
ASensorEvent buffer[16];
while ((n = q->read(buffer, 16)) >0) {
for (int i=0 ; i<n ; i++) {
if (buffer[i].type ==SENSOR_TYPE_STEP_COUNTER) {
// step-counter returns auint64, but the java API only deals with floats
float value =float(buffer[i].u64.step_counter);
env->SetFloatArrayRegion(mScratch, 0, 1, &value);
} else {
env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data);
}
if (buffer[i].type ==SENSOR_TYPE_META_DATA) {
// This is a flush completesensor event. Call dispatchFlushCompleteEvent
// method.
if (receiverObj.get()) {
env->CallVoidMethod(receiverObj.get(),
gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
buffer[i].meta_data.sensor);
}
} else {
int8_t status;
switch (buffer[i].type) {
caseSENSOR_TYPE_ORIENTATION:
caseSENSOR_TYPE_MAGNETIC_FIELD:
caseSENSOR_TYPE_ACCELEROMETER:
case SENSOR_TYPE_GYROSCOPE:
caseSENSOR_TYPE_GRAVITY:
caseSENSOR_TYPE_LINEAR_ACCELERATION:
status =buffer[i].vector.status;
break;
caseSENSOR_TYPE_HEART_RATE:
status = buffer[i].heart_rate.status;
break;
default:
status =SENSOR_STATUS_ACCURACY_HIGH;
break;
}
if (receiverObj.get()) {
env->CallVoidMethod(receiverObj.get(), gBaseEventQueueClassInfo.dispatchSensorEvent,
buffer[i].sensor,
mScratch,
status,
buffer[i].timestamp);
}
}
if (env->ExceptionCheck()) {
mSensorQueue->sendAck(buffer, n);
ALOGE("Exceptiondispatching input event.");
return 1;
}
}
mSensorQueue->sendAck(buffer, n);
}
if (n<0 && n != -EAGAIN) {
// FIXME: error receiving events, what to do in this case?
}
return 1;
}
};
step 6.1.5:
frameworks\native\libs\gui\SensorEventQueue.cpp
ssize_tSensorEventQueue::read(ASensorEvent* events, size_t numEvents) {
if (mAvailable == 0) {
ssize_t err = BitTube::recvObjects(mSensorChannel,
mRecBuffer,MAX_RECEIVE_BUFFER_EVENT_COUNT);
if (err < 0) {
return err;
}
mAvailable = static_cast<size_t>(err);
mConsumed = 0;
}
size_t count = min(numEvents, mAvailable);
memcpy(events, mRecBuffer + mConsumed, count * sizeof(ASensorEvent));
mAvailable -= count;
mConsumed += count;
return static_cast<ssize_t>(count);
}
SensorEventQueue的addSensor如下:
step :6.2.1
\frameworks\base\core\java\android\hardware\SystemSensorManager.java
public boolean addSensor(
Sensor sensor, int delayUs, intmaxBatchReportLatencyUs) {
// Check if already present.
int handle = sensor.getHandle();
if (mActiveSensors.get(handle)) return false;
// Get ready to receive events before calling enable.
mActiveSensors.put(handle, true);
addSensorEvent(sensor);
if (enableSensor(sensor, delayUs,maxBatchReportLatencyUs) != 0) {
// Try continuous mode ifbatching fails.
if (maxBatchReportLatencyUs ==0 ||
maxBatchReportLatencyUs> 0 && enableSensor(sensor, delayUs, 0) != 0) {
removeSensor(sensor, false);
return false;
}
}
return true;
}
step 6.2.2:
\frameworks\base\core\java\android\hardware\SystemSensorManager.java
private int enableSensor(
Sensor sensor, int rateUs, intmaxBatchReportLatencyUs) {
if (nSensorEventQueue == 0) throw new NullPointerException();
if (sensor == null) throw newNullPointerException();
return nativeEnableSensor(nSensorEventQueue,sensor.getHandle(), rateUs,
maxBatchReportLatencyUs);
}
step 6.2.3:
\frameworks\base\core\jni\android_hardware_SensorManager.cpp
static jint nativeEnableSensor(JNIEnv *env,jclass clazz, jlong eventQ, jint handle, jint rate_us,
jintmaxBatchReportLatency) {
sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
return receiver->getSensorEventQueue()->enableSensor(handle,rate_us, maxBatchReportLatency,
0);
}
step 6.2.4:
\frameworks\native\libs\gui\SensorEventQueue.cpp
status_t SensorEventQueue::enableSensor(Sensorconst* sensor) const {
return mSensorEventConnection->enableDisable(sensor->getHandle(),true, 0, 0, false);
}
step 6.2.5:
\frameworks\native\libs\gui\SurfaceComposerClient.cpp
virtual status_t enableDisable(int handle, bool enabled, nsecs_tsamplingPeriodNs,
nsecs_tmaxBatchReportLatencyNs, int reservedFlags)
{
Parcel data, reply;
data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor());
data.writeInt32(handle);
data.writeInt32(enabled);
data.writeInt64(samplingPeriodNs);
data.writeInt64(maxBatchReportLatencyNs);
data.writeInt32(reservedFlags);
remote()->transact(ENABLE_DISABLE, data, &reply);
return reply.readInt32();
}
step 6.2.6:
frameworks\native\services\sensorservice\SensorService.cpp
status_tSensorService::SensorEventConnection::enableDisable(
int handle, bool enabled, nsecs_t samplingPeriodNs, nsecs_tmaxBatchReportLatencyNs,
int reservedFlags)
{
status_t err;
if (enabled) {
err = mService->enable(this, handle,samplingPeriodNs, maxBatchReportLatencyNs,
reservedFlags,mOpPackageName);
}else {
err = mService->disable(this, handle);
}
return err;
}
step 6.2.7:
frameworks\native\services\sensorservice\SensorService.cpp
status_t SensorService::enable(constsp<SensorEventConnection>& connection,
int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs,int reservedFlags,
const String16& opPackageName)
{
if (mInitCheck != NO_ERROR)
return mInitCheck;
SensorInterface* sensor = mSensorMap.valueFor(handle);
if (sensor == NULL) {
return BAD_VALUE;
}
if (!canAccessSensor(sensor->getSensor(), "Tried enabling",opPackageName)) {
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
if ((mCurrentOperatingMode == RESTRICTED || mCurrentOperatingMode ==DATA_INJECTION)
&& !isWhiteListedPackage(connection->getPackageName())) {
return INVALID_OPERATION;
}
SensorRecord* rec = mActiveSensors.valueFor(handle);
if (rec == 0) {
rec = new SensorRecord(connection);
mActiveSensors.add(handle, rec);
if (sensor->isVirtual()) {
mActiveVirtualSensors.add(handle, sensor);
}
}else {
if (rec->addConnection(connection)) {
// this sensor is already activated, but we are adding a connection thatuses it.
// Immediately send down the last known value of the requested sensor ifit's not a
// "continuous" sensor.
if (sensor->getSensor().getReportingMode() ==AREPORTING_MODE_ON_CHANGE) {
// NOTE: The wake_up flag ofthis event may get set to
//WAKE_UP_SENSOR_EVENT_NEEDS_ACK if this is a wake_up event.
CircularBuffer *circular_buf =mLastEventSeen.valueFor(handle);
if (circular_buf) {
sensors_event_t event;
memset(&event, 0,sizeof(event));
// It is unlikely that thisbuffer is empty as the sensor is already active.
// One possible corner casemay be two applications activating an on-change
// sensor at the same time.
if(circular_buf->populateLastEvent(&event)) {
event.sensor = handle;
if (event.version ==sizeof(sensors_event_t)) {
if(isWakeUpSensorEvent(event) && !mWakeLockAcquired) {
setWakeLockAcquiredLocked(true);
}
connection->sendEvents(&event, 1, NULL);
if(!connection->needsWakeLock() && mWakeLockAcquired) {
checkWakeLockStateLocked();
}
}
}
}
}
}
}
if (connection->addSensor(handle)) {
BatteryService::enableSensor(connection->getUid(), handle);
// the sensor was added (which means it wasn't already there)
// so, see if this connection becomes active
if (mActiveConnections.indexOf(connection) < 0) {
mActiveConnections.add(connection);
}
}else {
ALOGW("sensor %08x already enabled in connection %p(ignoring)",
handle, connection.get());
}
nsecs_t minDelayNs = sensor->getSensor().getMinDelayNs();
if (samplingPeriodNs < minDelayNs) {
samplingPeriodNs = minDelayNs;
}
ALOGD_IF(DEBUG_CONNECTIONS, "Calling batch handle==%dflags=%d"
"rate=%" PRId64 " timeout== %" PRId64"",
handle, reservedFlags, samplingPeriodNs, maxBatchReportLatencyNs);
status_t err = sensor->batch(connection.get(), handle, 0,samplingPeriodNs,
maxBatchReportLatencyNs);
// Call flush() before calling activate() on the sensor. Wait for afirst flush complete
// event before sending events on this connection. Ignore one-shotsensors which don't
// support flush(). Also if this sensor isn't already active, don't callflush().
if (err == NO_ERROR && sensor->getSensor().getReportingMode()!= AREPORTING_MODE_ONE_SHOT &&
rec->getNumConnections() > 1) {
connection->setFirstFlushPending(handle, true);
status_t err_flush = sensor->flush(connection.get(), handle);
// Flush may return error if the underlying h/w sensor uses an olderHAL.
if (err_flush == NO_ERROR) {
rec->addPendingFlushConnection(connection.get());
} else {
connection->setFirstFlushPending(handle, false);
}
}
if (err == NO_ERROR) {
ALOGD_IF(DEBUG_CONNECTIONS, "Calling activate on %d", handle);
err =sensor->activate(connection.get(), true);
}
if (err == NO_ERROR) {
connection->updateLooperRegistration(mLooper);
SensorRegistrationInfo ®_info =
mLastNSensorRegistrations.editItemAt(mNextSensorRegIndex);
reg_info.mSensorHandle = handle;
reg_info.mSamplingRateUs = samplingPeriodNs/1000;
reg_info.mMaxReportLatencyUs = maxBatchReportLatencyNs/1000;
reg_info.mActivated = true;
reg_info.mPackageName = connection->getPackageName();
time_t rawtime = time(NULL);
struct tm * timeinfo = localtime(&rawtime);
reg_info.mHour = timeinfo->tm_hour;
reg_info.mMin = timeinfo->tm_min;
reg_info.mSec = timeinfo->tm_sec;
mNextSensorRegIndex = (mNextSensorRegIndex + 1) %SENSOR_REGISTRATIONS_BUF_SIZE;
}
if (err != NO_ERROR) {
// batch/activate has failed, reset our state.
cleanupWithoutDisableLocked(connection, handle);
}
return err;
}
step 6.2.8:
frameworks\native\services\sensorservice\SensorInterface.cpp
status_t HardwareSensor::activate(void*ident, bool enabled) {
return mSensorDevice.activate(ident,mSensor.getHandle(), enabled);
}
step 6.2.9:
frameworks\native\services\sensorservice\SensorDevice.cpp
status_t SensorDevice::activate(void*ident, int handle, int enabled)
{
if (!mSensorDevice) return NO_INIT;
status_t err(NO_ERROR);
bool actuateHardware = false;
Mutex::Autolock _l(mLock);
Info& info( mActivationCount.editValueFor(handle) );
ALOGD_IF(DEBUG_CONNECTIONS,
"SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d,count=%zu",
ident, handle, enabled, info.batchParams.size());
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.numActiveClients() == 1) {
// This is the first connection,we need to activate the underlying h/w sensor.
actuateHardware = true;
}
} else {
// Log error. Every activate call should be preceded by a batch() call.
ALOGE("\t >>>ERROR: activate called without batch");
}
}else {
ALOGD_IF(DEBUG_CONNECTIONS, "disable index=%zd",info.batchParams.indexOfKey(ident));
if (info.removeBatchParamsForIdent(ident) >= 0) {
if (info.numActiveClients() == 0) {
// This is the last connection,we need to de-activate the underlying h/w sensor.
actuateHardware = true;
} else {
const int halVersion =getHalDeviceVersion();
if (halVersion >=SENSORS_DEVICE_API_VERSION_1_1) {
// Call batch for thissensor with the previously calculated best effort
// batch_rate and timeout.One of the apps has unregistered for sensor
// events, and the besteffort batch parameters might have changed.
ALOGD_IF(DEBUG_CONNECTIONS,
"\t>>> actuating h/w batch %d %d %" PRId64 "%" PRId64, handle,
info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
info.bestBatchParams.batchTimeout);
mSensorDevice->batch(mSensorDevice,handle,info.bestBatchParams.flags,
info.bestBatchParams.batchDelay,
info.bestBatchParams.batchTimeout);
}
}
} else {
// sensor wasn't enabled for this ident
}
if (isClientDisabledLocked(ident)) {
return NO_ERROR;
}
}
if (actuateHardware) {
ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activatehandle=%d enabled=%d", handle,
enabled);
err = mSensorDevice->activate(
reinterpret_cast<structsensors_poll_device_t *> (mSensorDevice), handle, enabled);
ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ?"activating" : "disabling", handle,
strerror(-err));
if (err != NO_ERROR && enabled) {
// Failure when enabling the sensor. Clean up on failure.
info.removeBatchParamsForIdent(ident);
}
}
// On older devices which do not support batch, call setDelay().
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(
reinterpret_cast<structsensors_poll_device_t *>(mSensorDevice),
handle,info.bestBatchParams.batchDelay);
}
return err;
}
/*
mSensorDevice会从HAL层获取到各个sensor 的相关信息。mSensorDevice->activate就是对应的各个SENSOR驱动里面的enable.具体可以看HAL层的分析。
SensorDevice::SensorDevice()
: mSensorDevice(0),
mSensorModule(0)
{
status_t err =hw_get_module(SENSORS_HARDWARE_MODULE_ID,
(hw_module_t const**)&mSensorModule);
ALOGE_IF(err,"couldn't load %s module (%s)",
SENSORS_HARDWARE_MODULE_ID, strerror(-err));
if(mSensorModule) {
err =sensors_open_1(&mSensorModule->common, &mSensorDevice);
ALOGE_IF(err, "couldn't open device for module %s (%s)",
SENSORS_HARDWARE_MODULE_ID, strerror(-err));
if(mSensorDevice) {
if(mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_1 ||
mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_2) {
ALOGE(">>>> WARNING <<< Upgrade sensor HAL toversion 1_3");
}
sensor_t const* list;
ssize_tcount = mSensorModule->get_sensors_list(mSensorModule, &list);
mActivationCount.setCapacity(count);
Infomodel;
for (size_t i=0 ; i<size_t(count) ; i++) {
mActivationCount.add(list[i].handle, model);
mSensorDevice->activate(
reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
list[i].handle, 0);
}
}
}
}
*/