Let's take a look at the sensormanager code.
Sensormanager framework Layer Code
@ Frameworks/base/CORE/Java/Android/hardware/sensormanager. Java
Public sensormanager (lodomainmainloiter) {mmainloiter = mainloiter; // As mentioned above, this is the activity's lodomainsynchronized (slisteners) {If (! Ssensormoduleinitialized) {ssensormoduleinitialized = true; nativeclassinit (); // it seems that the local method is called to initialize swindowmanager = iwindowmanager. stub. asinterface (servicemanager. getservice ("window"); // obtain the Windows service regardless of IF (swindowmanager! = NULL) {// if it's null we're re running in the system process // which won't get the rotated values try {srotation = swindowmanager. watchrotation (newirotationwatcher. stub () {public voidonrotationchanged (INT rotation) {sensormanager. this. onrotationchanged (rotation) ;}});} catch (RemoteException e) {}} // initialize the sensor list sensors_module_init (); // initialize sensor module final arraylist <Sensor> fulllist = sfullsensorslist; // sensor list maintained by sensormanager int I = 0; do {sensor = new sensor (); // create a sensor object, which is passed to the app. // call the module method to obtain the sensor device I = sensors_module_get_next_sensor (sensor, I); if (I> = 0) {// log. D (TAG, "found sensor:" + sensor. getname () + // ", handle =" + sensor. gethandle (); sensor. setlegacytype (getlegacysensortype (sensor. getType (); fulllist. add (sensor); // Add it to the sensor list maintained by Sm () shandletosensor. append (sensor. gethandle (), sensor) ;}} while (I> 0); spool = new sensoreventpool (sfullsensorslist. size () * 2); ssensorthread = new sensorthread (); // yo, it seems that the thread has been created }}}
Obviously, nativeclassinit (), sensors_module_init (), and sensors_module_get_next_sensor () are all implemented locally.
private static native void nativeClassInit();private static native int sensors_module_init();private static native intsensors_module_get_next_sensor(Sensor sensor, int next);
According to the previous Code experience, it is likely that there is a corresponding local code in the frameworks/base/CORE/corresponding to a JNI directory:
frameworks/base/core/java/android/hardware/SensorManager.javaframeworks/base/core/jni/android_hardware_SensorManager.cpp
Naturally, JNI has its local code. Let's take a look at the nativeclassinit function:
@ Frameworks/base/CORE/JNI/android_hardware_sensormanager.cpp
static voidnativeClassInit (JNIEnv *_env, jclass _this){ jclasssensorClass = _env->FindClass("android/hardware/Sensor"); SensorOffsets& sensorOffsets = gSensorOffsets; sensorOffsets.name =_env->GetFieldID(sensorClass, "mName", "Ljava/lang/String;"); sensorOffsets.vendor =_env->GetFieldID(sensorClass, "mVendor", "Ljava/lang/String;"); sensorOffsets.version =_env->GetFieldID(sensorClass, "mVersion", "I"); sensorOffsets.handle =_env->GetFieldID(sensorClass, "mHandle", "I"); sensorOffsets.type = _env->GetFieldID(sensorClass,"mType", "I"); sensorOffsets.range =_env->GetFieldID(sensorClass, "mMaxRange", "F"); sensorOffsets.resolution =_env->GetFieldID(sensorClass, "mResolution","F"); sensorOffsets.power =_env->GetFieldID(sensorClass, "mPower", "F"); sensorOffsets.minDelay =_env->GetFieldID(sensorClass, "mMinDelay", "I");}
The code is relatively simple. It is used to save the members of the sensor class at the Java framework layer to the gsensoroffsets struct in the local code.
Implementation of the local sensors_module_init () method:
static jintsensors_module_ini(JNIEnv *env, jclass clazz){ SensorManager::getInstance(); return 0;}
The getinstance method of sensormanager is called in the local code. This is a typical Singleton mode to obtain class objects. Note that sensormanager is a local class instead of the sensormanager class at the Java layer.
Definition of local sensormanager
@ Frameworks/base/include/GUI/sensormanager. h
class SensorManager : publicASensorManager, publicSingleton<SensorManager>{public: SensorManager(); ~SensorManager(); ssize_tgetSensorList(Sensor const* const** list) const; Sensor const*getDefaultSensor(int type); sp<SensorEventQueue> createEventQueue();private: //DeathRecipient interface voidsensorManagerDied(); status_tassertStateLocked() const;private: mutable MutexmLock; mutablesp<ISensorServer> mSensorServer; mutableSensor const** mSensorList; mutableVector<Sensor> mSensors; mutablesp<IBinder::DeathRecipient> mDeathObserver;};
Note that sensormanager inherits the asensormanager and generic class Singleton <sensormanager>, while the sensormanager class does not have getinstance, so it must be defined in asensormanager or Singleton.
@ Frameworks/base/include/utils/singleton. h
template <typename TYPE>class ANDROID_API Singleton{public: staticTYPE& getInstance() { Mutex::Autolock _l(sLock); TYPE*instance = sInstance; if(instance == 0) { instance = new TYPE(); sInstance = instance; } return*instance; } static boolhasInstance() { Mutex::Autolock _l(sLock); returnsInstance != 0; }protected: ~Singleton(){ }; Singleton() {};private: Singleton(const Singleton&); Singleton& operator = (const Singleton&); static MutexsLock; static TYPE*sInstance;};//---------------------------------------------------------------------------}; // namespace android
When you call the getinstance method for the first time, create a generic object: sensormanager, and then call this method to return the first created generic object.
1) create a local sensormanager
The local sensormanager is a singleton mode, and its construction method is relatively simple. Its main work is handed over to the assertstatelocked method:
@ Frameworks/base/libs/GUI/sensormanager. cpp
SensorManager::SensorManager() :mSensorList(0){ // okay we'renot locked here, but it's not needed during construction assertStateLocked();}status_t SensorManager::assertStateLocked() const { if(mSensorServer == NULL) { // try for one second constString16 name("sensorservice"); for (inti=0 ; i<4 ; i++) { status_t err = getService(name,&mSensorServer); if(err == NAME_NOT_FOUND) { usleep(250000); continue; } if(err != NO_ERROR) { return err; } break; } classDeathObserver : public IBinder::DeathRecipient { SensorManager& mSensorManger; virtual void binderDied(const wp<IBinder>& who) { LOGW("sensorservice died [%p]", who.unsafe_get()); mSensorManger.sensorManagerDied(); } public: DeathObserver(SensorManager& mgr) : mSensorManger(mgr) { } }; mDeathObserver = new DeathObserver(*const_cast<SensorManager*>(this)); mSensorServer->asBinder()->linkToDeath(mDeathObserver); mSensors= mSensorServer->getSensorList(); size_tcount = mSensors.size(); mSensorList = (Sensor const**)malloc(count * sizeof(Sensor*)); for(size_t i=0 ; i<count ; i++) { mSensorList[i] = mSensors.array() + i; } } returnNO_ERROR;}
In the assertstatelocked method, first obtain the sensorservice object through getservice, and then register the death listener for sensorservice. sensormanager and sensorservice do not ask for the same month of the same year, but only request the same month of the same year to die. Call getsensorlist to obtain the objects of all sensors, store them in msensorlist, and store them in the local space.
2) obtain the list in local sensormanager
In the above function call, call getservice to obtain the sensorservice service, and then execute msensorserver-> getsensorlist to obtain the sensor list provided by the Service:
Vector<Sensor> SensorService::getSensorList(){ return mUserSensorList;}
Please note that the above getsensorlist function only returns the musersensorlist. When will this variable be initialized?
According to section 2.1, when the sensorservice is initialized locally, musersensorlist is not initialized in the constructor, And the sensorservice has an onfirstref method, this method is automatically called when the sensorservice is strongly referenced for the first time. When was the first time sensorservice was strongly referenced?
Call getservice in the sensormanager: assertstatelocked method to obtain the sensorservice and save it to the msensorserver member variable.
Msensorserver is defined in frameworks/base/include/GUI/sensormanager. h:
class SensorManager : public ASensorManager, public Singleton<SensorManager>{ mutable sp<ISensorServer>mSensorServer; mutable Sensorconst** mSensorList; mutable Vector<Sensor> mSensors;};
Msensroserver is strongly referenced. Therefore, when a local sensormanager class object is created, the sensorservice is automatically referenced and the onfirstref method is automatically called:
@ Frameworks/base/services/sensorservice. cpp:
Void sensorservice: onfirstref () {logd ("nusensorservice starting... "); sensordevice & Dev (sensordevice: getinstance (); // create the sensordevice object Dev if (Dev. initcheck () = no_error) {sensor_tconst * List; ssize_tcount = Dev. getsensorlist (& list); // obtain the sensor device list if (count> 0 ){... For (ssize_t I = 0; I <count; I ++) {registersensor (New hardwaresensor (list [I]); // register the sensor obtained locally...} Constsensorfusion & fusion (sensorfusion: getinstance (); If (hasgyro) {// If a gyroscope device exists, register registervirtualsensor (newrotationvectorsensor (); // registervirtualsensor (New gravitysensor (list, count )); // virtual gravity sensor registervirtualsensor (New linearaccelerationsensor (list, count); // virtual accelerator // These are optional registervirtualsensor (New orientationsensor ()); // virtual direction sensor registervirtualsensor (New correctedgyrosensor (list, count); // real gyroscope // virtual debugging sensors... char value [property_value_max]; property_get ("debug. sensors ", value," 0 "); If (atoi (value) {registervirtualsensor (New gyrodriftsensor ()); // virtual gyro sensor} // build the sensor list returned tousers musersensorlist = msensorlist; If (hasgyro & (virtualsensorsneeds & (1 <sensor_type_rotation_vector ))) {// if we have the fancy sensor fusion, and it's not provided by the // Hal, use our own (fused) orientation sensor by removing the // Hal supplied one form the user list. if (orientationindex> = 0) {musersensorlist. removeitemsat (orientationindex) ;}} run ("sensorservice", priority_urgent_display); minitcheck = no_error ;}}}
The code above first creates the object Dev through sensordevice: getinstance () and calls Dev. getsensorlist (& list) is used to obtain the sensor list. The sensor list of the sensor_t type is extracted, the hardwaresensor object is created, and the registersensor method is passed to register the sensor through registersensor, then the sensorfusion object is created through the singleton model, and a series of virtual sensors are created and registered. there are doubts and great doubts. How can sensors still have virtual ones ?? In fact, you should pay attention to the first conditions of these sensors. If (hasgyro) indicates that if there is a gyroscope, these virtual devices will be created, and then you can look at these virtual devices: rotation, gravity, accelerator, these devices correspond to a physical hardware: gyroscope. Therefore, these devices exist logically and do not exist physically. After the virtual device is initialized, assign the msensorlist sensor list to musersensorlist. msensorlist is initialized by registersensor, and musersensorlist is the sensor list to be submitted to the Java framework layer, finally, the sensorservice thread is run using the run method. Let's take a look at the registersensor code:
void SensorService::registerSensor(SensorInterface* s){ sensors_event_t event; memset(&event,0, sizeof(event)); const Sensorsensor(s->getSensor()); // add to thesensor list (returned to clients) mSensorList.add(sensor); // add to ourhandle->SensorInterface mapping mSensorMap.add(sensor.getHandle(), s); // create anentry in the mLastEventSeen array mLastEventSeen.add(sensor.getHandle(), event);}
The code above shows that the imported hardwaresensor object is created as a sensor, added to the msensorlist vector table, and then added the hardwaresensor object to the msensromap key-value pair, add the new sensor event data encapsulation object event to the mlasteventseen key-value pair.
The following sequence diagram shows how to obtain the sensor list.
1) sensorservice monitors the capture of threads and sensor events
Let's take a look at the sensorservice thread. Remember that there is a thread class in the parent class of sensorservice. When the run method is called, a thread is created and the threadloop method is called.
Bool sensorservice: threadloop () {logd ("nusensorservice thread starting... "); const size_tnumeventmax = 16*(1 + mvirtualsensorlist. size (); sensors_event_t buffer [numeventmax]; sensors_event_t scratch [numeventmax]; sensordevice & device (sensordevice: getinstance (); const size_tvcount = mvirtualsensorlist. size (); ssize_tcount; do {// call the poll method of sensordevice. It seems that the Count = device is monitored multiple times. poll (buffer, numev Entmax); If (count <0) {LogE ("sensor poll failed (% s)", strerror (-count); break ;} // record the last data in each sensor returned by poll to the mlasteventseen recordlastvalue (buffer, count); // handlevirtual sensors processes virtual sensor data if (count & vcount) {sensors_event_t const * const event = buffer; // obtain the Virtual Sensor list constdefakeykeyedvector <int, sensorinterface *> virtualsensors (getactivevirtualsensors (); constsize_t activevirtualsensorco Unt = virtualsensors. size (); // Number of Virtual Sensors if (activevirtualsensorcount) {size_t K = 0; sensorfusion & fusion (sensorfusion: getinstance (); If (fusion. isenabled () {for (size_t I = 0; I <size_t (count); I ++) {fusion. process (event [I]); // process virtual sensor device events} For (size_t I = 0; I <size_t (count); I ++) {for (size_t J = 0; j <activevirtualsensorcount; j ++) {sensors_event_t out; If (virtualsensors. valueat (j)-> PR Ocess (& out, event [I]) {buffer [count + k] = out; k ++ ;}} if (k) {// record the last synthesized values recordlastvalue (& buffer [count], k); count + = K; // sort the buffer by time-stamps sorteventbuffer (buffer, count) ;}}// sendour events to clients... // obtain the sensor connection object list constsortedvector <WP <sensoreventconnection> activeconnections (getactiveconnections (); size_tnumconnections = activeconnec Tions. size (); For (size_t I = 0; I <numconnections; I ++) {sp <sensoreventconnection> connection (activeconnections [I]. promote (); If (connection! = 0) {// Send sensor data information connection-> sendevents (buffer, Count, scratch) to the specified sensor connection client );}}} while (count> = 0 | thread: exitpending (); // The logw ("exiting sensorservice: threadloop => aborting... "); abort (); Return false ;}
We can see that device. the poll method is blocked on the poll method of the sensordevice. It must be reading the data on the sensor hardware, saving the sensor data in the buff, and then calling the recordlastvalue method, only the latest data of the same type of sensor (the last group of data collected) is saved to the value range of the corresponding sensor in the key-value object mlasteventseen. If the sensor device is a virtual device, the sensorfusion. Process () method is called to process the virtual device data. Sensorfusion is associated with a sensordevice, which is a processing class of virtual sensor devices. It is responsible for the calculation, processing, device activation, setting delay, and obtaining power consumption information of virtual sensor data.
Let's review the entire process.
1. Create a sensormanager object and call the assertstatelocked method.
2. Call getservice in the assertstatelocked method to obtain the sensorservice service.
3. When sensorservice is strongly referenced for the first time, the onfirstref method is automatically called.
4. Obtain the sensordevice singleton object
6. Call the sensordevice. getsensorlist method to save the sensor_t list to sensorservice.
8. Call registersensor to register the sensor and add it to the msensorlist.
9. Start the sensorservice thread and prepare to listen to all registered sensor devices.
12. Multi-Channel monitoring of registered sensor devices. When a sensor event exists, the event information encapsulated by sensor_event_t is returned.
16. Record Device information that generates sensor events
17. Call getactiveconnections to obtain all the active client sensoreventconnection class objects.
19. Send sensor event information to the client