Android Sensor Native 源码分析_aosp源码解读

            needsWakeLock |= activeConnections[i]->needsWakeLock();
            // If the connection has one-shot sensors, it may be cleaned up after first trigger.
            // Early check for one-shot sensors.
            if (activeConnections[i]->hasOneShotSensors()) {
                cleanupAutoDisabledSensorLocked(activeConnections[i], mSensorEventBuffer,
                        count);
            }
        }
    }
	
	//若还有wake up 类型的sensor报上来的数据的话,需要继续持有wakelock
    if (mWakeLockAcquired && !needsWakeLock) {
        setWakeLockAcquiredLocked(false);
    }
} while (!Thread::exitPending());

ALOGW("Exiting SensorService::threadLoop => aborting...");
abort();
return false;

}


该方法就是用SensorDevice循环去HAL层取数据,若无数据则阻塞当前线程,若有数据,则封装SensorEventConnection发送出去。至此SensorService已经启动了。


##### 3.2.2 SensorManager的启动流程


从前一篇分析安卓Sensor 框架 Java API层的源码中我们知道,SystemSensorManager继承并实现SensorManager的虚方法,应用通过调用SensorManger的方法来达到其监听sensor数据的需求,而实际功能的实现者是SystemSensorManager,且SystemSensorManager中负责和Native层的SensorManager交互。安卓系统开机时在  
 frameworks/base/core/java/android/app/SystemServiceRegistry.java中创建SystemSensorManger实例:



registerService(Context.SENSOR_SERVICE, SensorManager.class,
new CachedServiceFetcher() {
@Override
public SensorManager createService(ContextImpl ctx) {
return new SystemSensorManager(ctx.getOuterContext(),
ctx.mMainThread.getHandler().getLooper());
}});
然后跳转到SystemSensorManager的构造方法中:
public SystemSensorManager(Context context, Looper mainLooper) {
synchronized (sLock) {
if (!sNativeClassInited) {
sNativeClassInited = true;
nativeClassInit();//native层offset初始化,没做什么其他事情
}
}
Log.e(“======>lkh”, Log.getStackTraceString(new Throwable()));

mMainLooper = mainLooper;
mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
mContext = context;
mNativeInstance = nativeCreate(context.getOpPackageName());
//mNativeInstance 保存native创建的 c++对象 SensorManager的引用,
//该对象通过getOpPackageName()返回的结果作为参数创建,并且2者保存在一个map里边,
//注意,此SensorManager为native层c++实现的,非面向应用用Java实现的SensorManager

// initialize the sensor list
for (int index = 0;; ++index) {
    Sensor sensor = new Sensor();
    if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
    mFullSensorsList.add(sensor);
    mHandleToSensor.put(sensor.getHandle(), sensor);
}
//获取SesorService的sensor list里边的所有sensor,每个sensor创建一个对应的java层的Sensor对象,
//并保存到链表里边,并将sensor handle和sensor一并保存到map里边

}
在加锁的情况下,如果没有初始化过Native层的类,则调用nativeClassInit() JNI方法初始化,调用nativeCreate()方法初始化SensorManager.cpp的实例,再调用nativeGetSensorAtIndex() jni方法初始化sensor列表,以上分析可知,当SystemSensorManager初始化时,SensorManager.cpp同时也初始化了。
static jlong
nativeCreate
(JNIEnv *env, jclass clazz, jstring opPackageName)
{
ScopedUtfChars opPackageNameUtf(env, opPackageName);
return (jlong) &SensorManager::getInstanceForPackage(String16(opPackageNameUtf.c_str()));
}
接下来跳入Native SensorManager的构造函数中:
SensorManager::SensorManager(const String16& opPackageName)
: mSensorList(0), mOpPackageName(opPackageName), mDirectConnectionHandle(1) {
// okay we’re not locked here, but it’s not needed during construction
assertStateLocked();
}

status_t SensorManager::assertStateLocked() {
bool initSensorManager = false;
if (mSensorServer == NULL) {
initSensorManager = true;
} else {
// Ping binder to check if sensorservice is alive.
status_t err = IInterface::asBinder(mSensorServer)->pingBinder();
if (err != NO_ERROR) {
initSensorManager = true;
}
}
if (initSensorManager) {
waitForSensorService(&mSensorServer);
LOG_ALWAYS_FATAL_IF(mSensorServer == nullptr, “getService(SensorService) NULL”);

    class DeathObserver : public IBinder::DeathRecipient {
        SensorManager& mSensorManager;
        virtual void binderDied(const wp<IBinder>& who) {
            ALOGW("sensorservice died [%p]", who.unsafe_get());
            mSensorManager.sensorManagerDied();
        }
    public:
        explicit DeathObserver(SensorManager& mgr) : mSensorManager(mgr) { }
    };

    mDeathObserver = new DeathObserver(*const_cast<SensorManager *>(this));
    IInterface::asBinder(mSensorServer)->linkToDeath(mDeathObserver);

    mSensors = mSensorServer->getSensorList(mOpPackageName);
    size_t count = mSensors.size();
    mSensorList =
            static_cast<Sensor const**>(malloc(count * sizeof(Sensor*)));
    LOG_ALWAYS_FATAL_IF(mSensorList == NULL, "mSensorList NULL");

    for (size_t i=0 ; i<count ; i++) {
        mSensorList[i] = mSensors.array() + i;
    }
}

return NO_ERROR;

}


上面代码主要做了3件事情:


1. 等待SensorService起来,获取到其指针
2. 注册一个DeathObserver,当sensorManagerDied()时,做一些清理操作
3. 获取sensorList里面的每一个sensor对象的地址


### 3.3 Sensor数据的分发


接下来分析SensorService如何将sensor数据分发到应用,上面SensorService启动时,我们知道SensorService启动了一个线程去执行threadLoop方法,这个方法首先调用SensorDevice::getInstance()方法,获取其实例引用,接下来就进入了一个调用SensorDevice::poll()方法的do while循环中,SensorDevice在其中扮演了十分重要的角色,主要通过该类从HAL层取数据,下面是SensorDevice的部分源码:



SensorDevice::SensorDevice()
mHidlTransportErrors(20), mRestartWaiter(new HidlServiceRegistrationWaiter()) {
//通过hidl与HAL层建立连接
if (!connectHidlService()) {
    return;
}

//获取开机时前面所说的第三方SO库注册的sensor,这个SO库一般就是直接与驱动进行通信对实际sensor进行开关和数据获取了,
//比如高通骁龙855的sensors.ssc.so通过qmi与slpi进行通信。
//这些sensor_t 类型的结构体,需要第三方的so库里边自己实现,每个结构体对象存储一个sensor的信息
checkReturn(mSensors->getSensorsList(
        [&](const auto &list) {
            const size_t count = list.size();

            mActivationCount.setCapacity(count);
            Info model;
            for (size_t i=0 ; i < count; i++) {
                sensor_t sensor;
                convertToSensor(list[i], &sensor);
                // Sanity check and clamp power if it is 0 (or close)
                if (sensor.power < minPowerMa) {
                    ALOGE("Reported power %f not deemed sane, clamping to %f",
                          sensor.power, minPowerMa);
                    sensor.power = minPowerMa;
                }
                mSensorList.push_back(sensor);//将HAL层注册的sensor保存起来,具体如何注册的,后面分析sensor HAL层部分再分析
				
				//保存该sensor的handle,具体数值是在前面所说的第三方SO库决定的,一般是从1开启按顺序叠加
                mActivationCount.add(list[i].sensorHandle, model);

                checkReturn(mSensors->activate(list[i].sensorHandle, 0 /* disable */));//关闭该sensor,以防开着没用漏电
            }
        }));

}

bool SensorDevice::connectHidlService() {
// SensorDevice will wait for HAL service to start if HAL is declared in device manifest.
size_t retry = 10;

while (retry-- > 0) {
	//......
	
    //通过hidl获取 android.hardware.sensors@1.0-service
    mSensors = ISensors::getService();
    if (mSensors == nullptr) {
        // no sensor hidl service found
        break;
    }
	
	//.......
}
return (mSensors != nullptr);

}


与HAL层如何交互的分析已经远远超出我负责的范畴了,这里不做深入分析。我们只需知道Native层的Sensor数据是通过SensorDevice去HAL取得的就行了。当数据上来后,通过做一些判断和处理然后再分发给应用,其中判断处理包括:是否应该丢弃数据,是否是flush数据,是否需要将数据给融合sensor,应用是否已经关闭该sensor等,处理后,通过SensorService::SensorEventConnection::sendEvents将数据发出,senEvent()函数代码如下:



status_t SensorService::SensorEventConnection::sendEvents(
sensors_event_t const* buffer, size_t numEvents,
sensors_event_t* scratch,
wp const * mapFlushEventsToConnections) {
// filter out events not for this connection

sensors_event_t* sanitizedBuffer = nullptr;

int count = 0;
Mutex::Autolock _l(mConnectionLock); 
if (scratch) {
    size_t i=0;
    while (i<numEvents) {
        //每个数据琢一处理
        int32_t sensor_handle = buffer[i].sensor;
        if (buffer[i].type == SENSOR_TYPE_META_DATA) {
            ALOGD_IF(DEBUG_CONNECTIONS, "flush complete event sensor==%d ",
                    buffer[i].meta_data.sensor);
            // Setting sensor_handle to the correct sensor to ensure the sensor events per
            // connection are filtered correctly.  buffer[i].sensor is zero for meta_data
            // events.
            sensor_handle = buffer[i].meta_data.sensor;
        }

        ssize_t index = mSensorInfo.indexOfKey(sensor_handle);
        //enable 一个sensor时,会保存该sensor的handle
        //确认一下若该sensor已经被disable了,那么就没有必要将该sensor的数据给到应用了
        //或者该应用没有注册该sensor的话,也是直接过滤掉
        // Check if this connection has registered for this sensor. If not continue to the
        // next sensor_event.
        if (index < 0) {
            ++i;
            continue;
        }

        FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
        // Check if there is a pending flush_complete event for this sensor on this connection.
        if (buffer[i].type == SENSOR_TYPE_META_DATA && flushInfo.mFirstFlushPending == true &&
                mapFlushEventsToConnections[i] == this) {
            flushInfo.mFirstFlushPending = false;
            ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ",
                    buffer[i].meta_data.sensor);
            ++i;
            continue;
        }

        // If there is a pending flush complete event for this sensor on this connection,
        // ignore the event and proceed to the next.
        if (flushInfo.mFirstFlushPending) {
            ++i;
            continue;
        }

        //过滤掉flush的数据后,将要给到应用的数据拷到scratch
        do {
            // Keep copying events into the scratch buffer as long as they are regular
            // sensor_events are from the same sensor_handle OR they are flush_complete_events
            // from the same sensor_handle AND the current connection is mapped to the
            // corresponding flush_complete_event.
            if (buffer[i].type == SENSOR_TYPE_META_DATA) {
                if (mapFlushEventsToConnections[i] == this) {
                    scratch[count++] = buffer[i];
                }
            } else {
                // Regular sensor event, just copy it to the scratch buffer.
				//若为false,即应用进入idle,那么就不将数据装进scratch在通过scratch给到应用,
                //否则就装进去
                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 {
    //这边不会走到不用管,感觉google这段代码有点多余哈哈
    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;//可能遇到空指针?  free 已经做了判断了
    return status_t(NO_ERROR);
}

#if DEBUG_CONNECTIONS
mEventsReceived += count;
#endif
//将最新的数据缓存到mEventCache,后面可以dump出来debug
if (mCacheSize != 0) {
// There are some events in the cache which need to be sent first. Copy this buffer to
// the end of cache.
if (mCacheSize + count <= mMaxCacheSize) {
memcpy(&mEventCache[mCacheSize], scratch, count * sizeof(sensors_event_t));
mCacheSize += count;
} else {
// Check if any new sensors have registered on this connection which may have increased
// 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.
int remaningCacheSize = mMaxCacheSize - mCacheSize;
if (remaningCacheSize != 0) {
memcpy(&mEventCache[mCacheSize], scratch,
remaningCacheSize * sizeof(sensors_event_t));
}
int numEventsDropped = count - remaningCacheSize;
countFlushCompleteEventsLocked(mEventCache, numEventsDropped);
// Drop the first “numEventsDropped” in the cache.
memmove(mEventCache, &mEventCache[numEventsDropped],
(mCacheSize - numEventsDropped) * sizeof(sensors_event_t));

        // Copy the remainingEvents in scratch buffer to the end of cache.
        memcpy(&mEventCache[mCacheSize - numEventsDropped], scratch + remaningCacheSize,
                                        numEventsDropped * sizeof(sensors_event_t));
    }
    delete sanitizedBuffer;
    return status_t(NO_ERROR);
}

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;
#endif
}
}

// NOTE: ASensorEvent and sensors_event_t are the same type.


//重点在这边,把scratch里边的数据发出去,
ssize_t size = SensorEventQueue::write(mChannel,
                                reinterpret_cast<ASensorEvent const*>(scratch), count);
if (size < 0) {
    // Write error, copy events to local cache.
    if (index_wake_up_event >= 0) {
        // If there was a wake_up sensor_event, reset the flag.
        scratch[index_wake_up_event].flags &= ~WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
        if (mWakeLockRefCount > 0) {
            --mWakeLockRefCount;
        }

#if DEBUG_CONNECTIONS
–mTotalAcksNeeded;
#endif
}
if (mEventCache == NULL) {
mMaxCacheSize = computeMaxCacheSizeLocked();
mEventCache = new sensors_event_t[mMaxCacheSize];
mCacheSize = 0;
}
memcpy(&mEventCache[mCacheSize], scratch, count * sizeof(sensors_event_t));
mCacheSize += count;

    // 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;
}

}


发现别无他法发送数据,唯有SensorEventQueue::write() 对复制得来的的scratch数据进行了处理,下面跳进该方法中:



ssize_t SensorEventQueue::write(const sp& tube,
ASensorEvent const* events, size_t numEvents) {
return BitTube::sendObjects(tube, events, numEvents);
}


该方法仅仅调用了一下BitTube::sendObjects()方法,只能进入此方法中查看:



ssize_t BitTube::sendObjects(const sp& tube,
void const* events, size_t count, size_t objSize)
{
//SensorService::SensorEventConnection::mChannel::write()
//mChannel 为 BitTube 对象
const char* vaddr = reinterpret_cast<const char*>(events);
ssize_t size = tube->write(vaddr, count*objSize);

// should never happen because of SOCK_SEQPACKET
LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),
        "BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were sent!)",
        count, objSize, size);
看到tube->write(),则继续跟进去看:

ssize_t BitTube::write(void const* vaddr, size_t size)
{
ssize_t err, len;
do {
//这边通过 unix域套接字 发出去
len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
// cannot return less than size, since we’re using SOCK_SEQPACKET
err = len < 0 ? errno : 0;
} while (err == EINTR);
return err == 0 ? len : -err;
}


这个send方法是 sys/socket.h中声明的,是Unix套接字,这里分析到发送端就结束了。  
 接下来分析接收端怎么接收的,应用是通过SensorManager注册一个SensorEventListener来接收数据的,主要是通过调用registerListener方法,代码如下:



public boolean registerListener(SensorEventListener listener, Sensor sensor,
int samplingPeriodUs, Handler handler) {
int delay = getDelay(samplingPeriodUs);
return registerListenerImpl(listener, sensor, delay, handler, 0, 0);
}
SystemSensorManager是SensorManager的实现类,其实现方法如下:
protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {
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 be non-negative”);
return false;
}
if (mSensorListeners.size() >= MAX_LISTENER_COUNT) {
throw new IllegalStateException("register failed, " +
"the sensor listeners size has exceeded the maximum limit " +
MAX_LISTENER_COUNT);
}

    // Invariants to preserve:
    // - one Looper per SensorEventListener
    // - one Looper per SensorEventQueue
    // We map SensorEventListener to a SensorEventQueue, which holds the looper
    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();
            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);
        }
    }
}

在各种合法性判断之后,先根据传入的listener获取对应的SensorEventQueue实例,如果不为空则调用addSensor方法,为空则创建该实例并调用addSensor方法最后将其加入mSensorListeners中,而创建实例时,会调用android/frameworks/base/core/jni/android\_hardware\_SensorManager.cpp nativeInitSensorEventQueue(),其源码如下:



static jlong nativeInitSensorEventQueue(JNIEnv env, jclass clazz, jlong sensorManager,
jobject eventQWeak, jobject msgQ, jstring packageName, jint mode) {
SensorManager
mgr = reinterpret_cast<SensorManager*>(sensorManager);
ScopedUtfChars packageUtf(env, packageName);
String8 clientName(packageUtf.c_str());
sp queue(mgr->createEventQueue(clientName, mode));

if (queue == NULL) {
    jniThrowRuntimeException(env, "Cannot construct native SensorEventQueue.");
    return 0;
}

sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);//获取MessageQueue
if (messageQueue == NULL) {
    jniThrowRuntimeException(env, "MessageQueue is not initialized.");
    return 0;
}

sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQWeak);
receiver->incStrong((void*)nativeInitSensorEventQueue);
return jlong(receiver.get());

}


这里创建了一个接收数据的Receiver对象,该类定义也在android\_hardwate\_SensorManager.cpp中,receiver又根据clientName创建了一个Native层的SensorEventQueue:



Receiver(const sp& sensorQueue,
const sp& messageQueue,
jobject receiverWeak) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
//保存传进来的2个比较关键的对象引用
mSensorQueue = sensorQueue;
mMessageQueue = messageQueue;

mReceiverWeakGlobal = env->NewGlobalRef(receiverWeak);

mIntScratch = (jintArray) env->NewGlobalRef(env->NewIntArray(16));
mFloatScratch = (jfloatArray) env->NewGlobalRef(env->NewFloatArray(16));

}
receiver在执行incStrong时,会顺带执行它自己的onFirstRef()方法:
virtual void onFirstRef() {
LooperCallback::onFirstRef();
//获取套接字fd
mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,
ALOOPER_EVENT_INPUT, this, mSensorQueue.get());

}


上面将SensorEventQueue中BitTube里通过unix socket创建的mReceiveFd,添加到looper里,在Looper::pollInner()方法中通过epoll监听该fd,当有事件时,就会回调Receiver::hanldeEvent(),接下来看该方法:



virtual int handleEvent(int fd, int events, void* data) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
sp q = reinterpret_cast<SensorEventQueue *>(data);
ScopedLocalRef receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
ssize_t n;
ASensorEvent buffer[16];
//这边最后是通过标准的socket接口recv将数据读取出来,代码在以下位置:
//android/frameworks/native/libs/sensor
//SensorEventQueue::read() > BitTube::recvObjects()>BitTube::read()
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 a uint64, but the java API only deals with floats
float value = float(buffer[i].u64.step_counter);
env->SetFloatArrayRegion(mFloatScratch, 0, 1, &value);
} else if (buffer[i].type == SENSOR_TYPE_DYNAMIC_SENSOR_META) {
float value[2];
value[0] = buffer[i].dynamic_sensor_meta.connected ? 1.f: 0.f;
value[1] = float(buffer[i].dynamic_sensor_meta.handle);
env->SetFloatArrayRegion(mFloatScratch, 0, 2, value);
} else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
env->SetIntArrayRegion(mIntScratch, 0, 14,
buffer[i].additional_info.data_int32);
env->SetFloatArrayRegion(mFloatScratch, 0, 14,
buffer[i].additional_info.data_float);
} else {
env->SetFloatArrayRegion(mFloatScratch, 0, 16, buffer[i].data);
}

            if (buffer[i].type == SENSOR_TYPE_META_DATA) {
                // This is a flush complete sensor event. Call dispatchFlushCompleteEvent
                // method.
                if (receiverObj.get()) {
                    env->CallVoidMethod(receiverObj.get(),
                                        gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
                                        buffer[i].meta_data.sensor);
                }
            } else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
                // This is a flush complete sensor event. Call dispatchAdditionalInfoEvent
                // method.
                if (receiverObj.get()) {
                    int type = buffer[i].additional_info.type;
                    int serial = buffer[i].additional_info.serial;
                    env->CallVoidMethod(receiverObj.get(),
                                        gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent,
                                        buffer[i].sensor,
                                        type, serial,
                                        mFloatScratch,
                                        mIntScratch,
                                        buffer[i].timestamp);
                }
            }else {
                int8_t status;
                switch (buffer[i].type) {
                case SENSOR_TYPE_ORIENTATION:
                case SENSOR_TYPE_MAGNETIC_FIELD:
                case SENSOR_TYPE_ACCELEROMETER:
                case SENSOR_TYPE_GYROSCOPE:
                case SENSOR_TYPE_GRAVITY:
                case SENSOR_TYPE_LINEAR_ACCELERATION:
                    status = buffer[i].vector.status;
                    break;
                case SENSOR_TYPE_HEART_RATE:
                    status = buffer[i].heart_rate.status;
                    break;
                default:
                    status = SENSOR_STATUS_ACCURACY_HIGH;
                    break;
                }
        //关键就在这里,这边通过jni回调SystemSensorManager::dispatchSensorEvent(),将数据给SensorManager
				
				
                if (receiverObj.get()) {
                    env->CallVoidMethod(receiverObj.get(),
                                        gBaseEventQueueClassInfo.dispatchSensorEvent, 
                                        buffer[i].sensor,
                                        mFloatScratch,
                                        status,
                                        buffer[i].timestamp);
                }
            }
            if (env->ExceptionCheck()) {
                mSensorQueue->sendAck(buffer, n);
                ALOGE("Exception dispatching input event.");
                return 1;
            }
        }
		//对SensorService::SensorEventConnection发送确认,
		//SensorService::SensorEventConnection::handleEvent()接收并确认
        mSensorQueue->sendAck(buffer, n);
    }
	        if (n<0 && n != -EAGAIN) {
        // FIXME: error receiving events, what to do in this case?
    }
    return 1;
}

总结

其实要轻松掌握很简单,要点就两个:

  1. 找到一套好的视频资料,紧跟大牛梳理好的知识框架进行学习。
  2. 多练。 (视频优势是互动感强,容易集中注意力)

你不需要是天才,也不需要具备强悍的天赋,只要做到这两点,短期内成功的概率是非常高的。

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。

以上就是总结的关于在面试的一些总结,希望对大家能有些帮助,除了这些面试中需要注意的问题,当然最重要的就是刷题了,这里放上我之前整理的一份超全的面试专题PDF

还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

这里只是整理出来的部分面试题,后续会持续更新,希望通过这些高级面试题能够降低面试Android岗位的门槛,让更多的Android工程师理解Android系统,掌握Android系统。喜欢的话麻烦点击一个喜欢在关注一下~

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

的。**

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。

以上就是总结的关于在面试的一些总结,希望对大家能有些帮助,除了这些面试中需要注意的问题,当然最重要的就是刷题了,这里放上我之前整理的一份超全的面试专题PDF

还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

[外链图片转存中…(img-C1fejyp7-1714289483851)]

这里只是整理出来的部分面试题,后续会持续更新,希望通过这些高级面试题能够降低面试Android岗位的门槛,让更多的Android工程师理解Android系统,掌握Android系统。喜欢的话麻烦点击一个喜欢在关注一下~

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 12
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值