[Android] GPS start process and data flow direction analysis (based on 2.3.5)

Source: Internet
Author: User

GPS start process and data flow direction analysis:

First, in the system init stage, many services will be added through ServiceManager addService, which includes the LocationService.
The code is in SystemServer. java:

Try {
Slog. I (TAG, "Location Manager ");
Location = new LocationManagerService (context );
ServiceManager. addService (Context. LOCATION_SERVICE, location );
} Catch (Throwable e ){
ReportWtf ("starting Location Manager", e );
} Then call the systemReady function of the LocationManagerService to start a thread. Final LocationManagerService locationF = location;
Try {
If (locationF! = Null) locationF. systemReady ();
} Catch (Throwable e ){
ReportWtf ("making Location Service ready", e );
} -- LocationManagerService. java void systemReady (){
// We defer starting up the service until the system is ready
Thread thread = new Thread (null, this, "LocationManagerService ");
Thread. start ();
} Prepare for receiving messages in the run function of Thread and call an initialize function: public void run ()
{
Process. setThreadPriority (Process. THREAD_PRIORITY_BACKGROUND );
Logoff. prepare ();
MLocationHandler = new LocationWorkerHandler ();
Initialize ();
Logoff. loop ();
} Then let's see initialize (): private void initialize (){
// Create a wake lock, needs to be done before calling loadProviders () below
PowerManager powerManager = (PowerManager) mContext. getSystemService (Context. POWER_SERVICE );
MWakeLock = powerManager. newWakeLock (PowerManager. PARTIAL_WAKE_LOCK, WAKELOCK_KEY );

// Load providers
LoadProviders ();

// Register for Network (Wifi or Mobile) updates
IntentFilter intentFilter = new IntentFilter ();
IntentFilter. addAction (ConnectivityManager. CONNECTIVITY_ACTION );
// Register for Package Manager updates
IntentFilter. addAction (Intent. ACTION_PACKAGE_REMOVED );
IntentFilter. addAction (Intent. ACTION_PACKAGE_RESTARTED );
IntentFilter. addAction (Intent. ACTION_QUERY_PACKAGE_RESTART );
MContext. registerReceiver (mBroadcastReceiver, intentFilter );
IntentFilter sdFilter = new IntentFilter (Intent. ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE );
MContext. registerReceiver (mBroadcastReceiver, sdFilter );

// Listen for settings changes
ContentResolver resolver = mContext. getContentResolver ();
Cursor settingsCursor = resolver. query (Settings. Secure. CONTENT_URI, null,
"(" + Settings. System. NAME + "= ?) ",
New String [] {Settings. Secure. LOCATION_PROVIDERS_ALLOWED },
Null );
Msethandler = new ContentQueryMap (settingsCursor, Settings. System. NAME, true, mLocationHandler );
SettingsObserver settingsObserver = new SettingsObserver ();
MSettings. addObserver (settingsObserver );
} There are two important points:
1) loadProviders (), a new GpsLocationProvider will be added, and a chain table of ArrayList <LocationProviderInterface> will be added to this GpsLocationProvider.
2) A new SettingsObserver object, which is responsible for notifying local programs to handle data changes in Settings. The SettingsObserver class implements the Observer interface, and the update function in this interface should be a callback function. When data changes in Settings, it will be called back to this function: private final class SettingsObserver implements Observer {
Public void update (Observable o, Object arg ){
Synchronized (mLock ){
UpdateProvidersLocked ();
}
}
}

Private void updateProvidersLocked (){
Boolean changesMade = false;
For (int I = mProviders. size ()-1; I> = 0; I --){
LocationProviderInterface p = mProviders. get (I );
Boolean isEnabled = p. isEnabled ();
String name = p. getName ();
Boolean shouldBeEnabled = isAllowedBySettingsLocked (name );
If (isEnabled &&! ShouldBeEnabled ){
UpdateProviderListenersLocked (name, false );
ChangesMade = true;
} Else if (! IsEnabled & shouldBeEnabled ){
UpdateProviderListenersLocked (name, true );
ChangesMade = true;
}
}
If (changesMade ){
MContext. sendBroadcast (new Intent (LocationManager. PROVIDERS_CHANGED_ACTION ));
}
}

Private void updateProviderListenersLocked (String provider, boolean enabled ){
Int listeners = 0;

LocationProviderInterface p = mProvidersByName. get (provider );
If (p = null ){
Return;
}

ArrayList <Cycler> deadReceivers = null;

ArrayList <UpdateRecord> records = mRecordsByProvider. get (provider );
If (records! = Null ){
Final int N = records. size ();
For (int I = 0; I <N; I ++ ){
UpdateRecord record = records. get (I );
// Sends a notification message to the specified er
If (! Record. mReceiver. callProviderEnabledLocked (provider, enabled )){
If (deadReceivers = null ){
DeadReceivers = new ArrayList <Receiver ER> ();
}
DeadReceivers. add (record. mReceiver );
}
Listeners ++;
}
}

If (deadReceivers! = Null ){
For (int I = deadReceivers. size ()-1; I> = 0; I --){
RemoveUpdatesLocked (deadReceivers. get (I ));
}
}

If (enabled ){
P. enable ();
If (listeners> 0 ){
P. setMinTime (getMinTimeLocked (provider), mTmpWorkSource );
P. enableLocationTracking (true );
}
} Else {
P. enableLocationTracking (false );
P. disable ();
}
} In the updateProviderListenersLocked function, LocationProviderInterface p is used to call enable or disable the location service. The following code calls enable or disable in GpsLocationProvider, a subclass of LocationProviderInterface:
 
GpsLocationProvider. java public void enable (){
Synchronized (mHandler ){
SendMessage (ENABLE, 1, null );
}
} Handlenable is the message processing function of ENABLE: private void handleEnable (){
If (DEBUG) Log. d (TAG, "handleEnable ");
If (mEnabled) return;
MEnabled = native_init ();

Intent intent = new Intent (LocationManager. GPS_SETTING_ENABLED_CHANGE_ACTION );
Intent. putExtra (LocationManager. EXTRA_GPS_ENABLED, mEnabled );
MContext. sendBroadcast (intent );

If (mEnabled ){
MSupportsXtra = native_supports_xtra ();
If (mSuplServerHost! = Null ){
Native_set_agps_server (AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort );
}
If (mC2KServerHost! = Null ){
Native_set_agps_server (AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort );
}
} Else {
Log. w (TAG, "Failed to enable location provider ");
}
} Now we can see that communication with the native layer has started.
Native_init corresponds to the android_location_GpsLocationProvider_init function in jni, which calls
SGpsInterface-> init (& sGpsCallbacks ),
SGpsCallbacks is defined as follows: GpsCallbacks sGpsCallbacks = {
Sizeof (GpsCallbacks ),
Location_callback,
Status_callback,
Sv_status_callback,
Nmea_callback,
Set_capabilities_callback,
Acquire_wakelock_callback,
Release_wakelock_callback,
Create_thread_callback,
Request_utc_time_callback,
}; This is to pass some jni functions as parameters to the native c space, so that if there is available data in native c, the functions in jni will be called through callback. Let's take a brief look at the definition of location_callback: static void location_callback (GpsLocation * location)
{
JNIEnv * env = AndroidRuntime: getJNIEnv ();
Env-> CallVoidMethod (mCallbacksObj, method_reportLocation, location-> flags,
(Jdouble) location-> latitude, (jdouble) location-> longpolling,
(Jdouble) location-> altitude,
(Jfloat) location-> speed, (jfloat) location-> bearing,
(Jfloat) location-> accuracy, (jlong) location-> timestamp );
CheckAndClearExceptionFromCallback (env, _ FUNCTION __);
}

It is defined as follows:
Static jmethodID method_reportLocation; and:
Method_reportLocation = env-> GetMethodID (clazz, "reportLocation", "(IDDDFFFJ) V ");
It can be seen that the callback function in jni actually calls back the reportLocation function in the java Framework, which is the data flow structure of the whole GPS Framework. All data is notified to the upper layer through callback:
NativeC notifies JNI through callback, and JNI notifies Framework through callback. This should be the most important part of the gps framework. It is easy to understand the data flow.
Our native c does not implement the native_set_agps_server function, so the data server using agps is not specified at the upper layer, but directly specified in the c file. Native_set_agps_server is only an empty function.

The above describes the functions of sGpsCallbacks in sGpsInterface> init (& sGpsCallbacks), but the init function call has not been analyzed:
SGpsInterface is defined as follows:
Static const GpsInterface * sGpsInterface = NULL;
It is initialized in the android_location_GpsLocationProvider_class_init_native function, which is pre-loaded in GpsLocationProvider in static mode:

Err = hw_get_module (GPS_HARDWARE_MODULE_ID, (hw_module_t const **) & module );
If (err = 0 ){
Hw_device_t * device;
// By calling open, a gps_device_t space is allocated at the native layer and passed back.
Err = module-> methods-> open (module, GPS_HARDWARE_MODULE_ID, & device );
If (err = 0 ){
// This forced conversion is because the first item in gps_device_t is an hw_device_t.
// It is indeed the allocated gps_device_t space in native.
Gps_device_t * gps_device = (gps_device_t *) device;
SGpsInterface = gps_device-> get_gps_interface (gps_device );
}
}

 

This sGpsInterface is obtained from hwModule. Let's take a look at the get_gps_interface function: static int open_gps (const struct hw_module_t * module, char const * name,
Struct hw_device_t ** device)
{
Struct gps_device_t * dev = malloc (sizeof (struct gps_device_t ));
If (dev = NULL ){
LOGE ("gps device can not malloc memery! ");
Return-ENOMEM;
}

Memset (dev, 0, sizeof (* dev ));
Dev-> common. tag = HARDWARE_DEVICE_TAG;
Dev-> common. version = 0;
Dev-> common. module = (struct hw_module_t *) module;
Dev-> common. close = close_gps;
// Note that one parameter has no Parameter
Dev-> get_gps_interface = gps_get_hardware_interface;
* Device = (struct hw_device_t *) dev;

Return 0;
}

Const GpsInterface * gps_get_hardware_interface ()
{
Return & ubloxGpsInterface;
}

/* Gps interface struct */
Static const GpsInterface ubloxGpsInterface =
{
. Size = sizeof (GpsInterface ),
. Init = ublox_gps_init,
. Start = ublox_gps_start,
. Stop = ublox_gps_stop,
. Cleanup = ublox_gps_cleanup,
. Inject_location = ublox_gps_inject_location,
. Delete_aiding_data = ublox_gps_delete_aiding_data,
. Set_position_mode = ublox_gps_set_position_mode,
. Get_extension = ublox_gps_get_extension,
};

Static int ublox_gps_init (GpsCallbacks * callbacks)
{
UbloxGpsData * gps_data = & ublox_gps_data;

// Ubox gps support MS-based A-GPS, fix in the gps terminal
Callbacks-> set_capabilities_cb (GPS_CAPABILITY_SCHEDULING | GPS_CAPABILITY_MSB );

Pthread_mutex_init (& gps_data-> deferred_action_mutex, NULL );
Pthread_cond_init (& gps_data-> deferred_action_cond, NULL );
Agps_state-> used_proxy = 0;

Gps_data-> gps_callbacks = * callbacks;
Gps_data-> thread_start = 0;

LOGD ("gps finishes initialization ");

Return 0;
} So sGpsInterface actually points to the ubloxGpsInterface of the native layer. Call the init function to pass the callback function of the JNI space to the native space.
The Application Layer calls Settings. Secure. setLocationProviderEnabled (
Resolver,
LocationManager. GPS_PROVIDER,
DesiredState); enable or Disable location service.

Url: http://greatverve.cnblogs.com/archive/2012/01/31/android-gps.html

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.