Android系统Gps分析

Android系统Gps分析

 

1GPS架构:

 

2GPS分析:

2.1头文件:

头文件定义在头文件定义在:hardware/libhardware/include/hardware/gps.h,定义了GPS底层相关的结构体和接口:

1,GpsLocationGPS位置信息结构体,包含经度,纬度,高度,速度,方位角等.

 typedef struct {

 

     /** set to sizeof(GpsLocation) */

 

     size_t          size;

 

     /** Contains GpsLocationFlags bits. */

 

     uint16_t        flags;

 

     /** Represents latitude in degrees. */

 

     double          latitude;

 

     /** Represents longitude in degrees. */

 

     double          longitude;

 

     /** Represents altitude in meters above the WGS 84 reference

 

      * ellipsoid. */

 

     double          altitude;

 

     /** Represents speed in meters per second. */

 

     float           speed;

 

     /** Represents heading in degrees. */

 

     float           bearing;

 

     /** Represents expected accuracy in meters. */

 

     float           accuracy;

 

     /** Timestamp for the location fix. */

 

     GpsUtcTime      timestamp;

 

 } GpsLocation;

 

 

2,GpsStatus:GPS状态包括5种状态,分别为未知,正在定位,停止定位,启动未定义,未启动。

 typedef struct {

 

     /** set to sizeof(GpsStatus) */

 

     size_t          size;

 

     GpsStatusValue status;

 

 } GpsStatus;

 

 

3GpsSvInfo:GPS卫星信息,包含卫星编号,信号强度,卫星仰望角,方位角等。

 typedef struct {

 

     /** set to sizeof(GpsSvInfo) */

 

     size_t          size;

 

     /** Pseudo-random number for the SV. */

 

     int     prn;

 

     /** Signal to noise ratio. */

 

     float   snr;

 

     /** Elevation of SV in degrees. */

 

     float   elevation;

 

     /** Azimuth of SV in degrees. */

 

     float   azimuth;

 

 } GpsSvInfo;

 

 

4GpsSvStatusGPS卫星状态,包含可见卫星数和信息,星历时间,年历时间等。

 typedef struct {

 

     /** set to sizeof(GpsSvStatus) */

 

     size_t          size;

 

 

 

     /** Number of SVs currently visible. */

 

     int         num_svs;

 

 

 

     /** Contains an array of SV information. */

 

     GpsSvInfo   sv_list[GPS_MAX_SVS];

 

 

 

     /** Represents a bit mask indicating which SVs

 

      * have ephemeris data.

 

      */

 

     uint32_t    ephemeris_mask;

 

 

 

     /** Represents a bit mask indicating which SVs

 

      * have almanac data.

 

      */

 

     uint32_t    almanac_mask;

 

 

 

     /**

 

      * Represents a bit mask indicating which SVs

 

      * were used for computing the most recent position fix.

 

      */

 

     uint32_t    used_in_fix_mask;

 

 } GpsSvStatus;

 

 

5GpsCallbacks:

/** Callback with location information.

 

 *  Can only be called from a thread created by create_thread_cb.

 

 */

 

typedef void (* gps_location_callback)(GpsLocation* location);

//向上层传递GPS位置信息

 

 

/** Callback with status information.

 

 *  Can only be called from a thread created by create_thread_cb.

 

 */

 

typedef void (* gps_status_callback)(GpsStatus* status);

//向上层传递GPS状态信息

 

 

/** Callback with SV status information.

 

 *  Can only be called from a thread created by create_thread_cb.

 

 */

 

typedef void (* gps_sv_status_callback)(GpsSvStatus* sv_info);

//向上层传递GPS卫星信息

 

 

/** Callback for reporting NMEA sentences.

 

 *  Can only be called from a thread created by create_thread_cb.

 

 */

 

typedef void (* gps_nmea_callback)(GpsUtcTime timestamp, const char* nmea, int length);

//向上层传递NMEA数据

 

 

/** Callback to inform framework of the GPS engine's capabilities.

 

 *  Capability parameter is a bit field of GPS_CAPABILITY_* flags.

 

 */

 

typedef void (* gps_set_capabilities)(uint32_t capabilities);//告知GPS模块可以实现的功能

 

 

 

/** Callback utility for acquiring the GPS wakelock.

 

 *  This can be used to prevent the CPU from suspending while handling GPS events.

 

 */

 

typedef void (* gps_acquire_wakelock)();

//上锁,防止处理GPS时间时终止

 

 

/** Callback utility for releasing the GPS wakelock. */

 

typedef void (* gps_release_wakelock)();

//释放锁

 

 

/** Callback for creating a thread that can call into the Java framework code.

 

 *  This must be used to create any threads that report events up to the framework.

 

 */

 

 typedef pthread_t (* gps_create_thread)(const char* name, void (*start)(void *), void* arg);

//等待上层请求

 

 

 /** GPS callback structure. */

 

 typedef struct {

 

     /** set to sizeof(GpsCallbacks) */

 

     size_t      size;

 

     gps_location_callback location_cb;

 

     gps_status_callback status_cb;

 

     gps_sv_status_callback sv_status_cb;

 

     gps_nmea_callback nmea_cb;

 

     gps_set_capabilities set_capabilities_cb;

 

     gps_acquire_wakelock acquire_wakelock_cb;

 

     gps_release_wakelock release_wakelock_cb;

 

     gps_create_thread create_thread_cb;

 

 } GpsCallbacks;

 

 

6GpsInterfaceGPS最重要的结构体,上层通过次接口与硬件适配层交互的。

/** Represents the standard GPS interface. */

 

typedef struct {

 

    /** set to sizeof(GpsInterface) */

 

    size_t          size;

 

    /**

 

     * Opens the interface and provides the callback routines

 

     * to the implemenation of this interface.

 

     */

 

    int   (*init)( GpsCallbacks* callbacks );

 

 

 

    /** Starts navigating. */

 

    int   (*start)( void );

//启动定位

 

 

    /** Stops navigating. */

 

    int   (*stop)( void );

//取消定位

 

 

    /** Closes the interface. */

 

    void  (*cleanup)( void );

//关闭GPS接口

 

 

    /** Injects the current time. */

 

    int   (*inject_time)(GpsUtcTime time, int64_t timeReference,

 

                         int uncertainty);

//填入时间

 

 

    /** Injects current location from another location provider

 

     *  (typically cell ID).

 

     *  latitude and longitude are measured in degrees

 

     *  expected accuracy is measured in meters

 

     */

 

    int  (*inject_location)(double latitude, double longitude, float accuracy);

//填入位置

 

 

    /**

 

     * Specifies that the next call to start will not use the

 

     * information defined in the flags. GPS_DELETE_ALL is passed for

 

     * a cold start.

 

     */

 

    void  (*delete_aiding_data)(GpsAidingData flags);

//删除全部或部分辅助数据,在性能测试时使用

     /**

 

      * min_interval represents the time between fixes in milliseconds.

 

      * preferred_accuracy represents the requested fix accuracy in meters.

 

      * preferred_time represents the requested time to first fix in milliseconds.

 

      */

 

     int   (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,

 

             uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);

//设置定位模式和GPS工作模式等

 

 

     /** Get a pointer to extension information. */

 

     const void* (*get_extension)(const char* name);

//自定义的接口

 } GpsInterface;

 

 

7gps_device_t:GPS设备结构体,向上层提供了重要的get_gps_interface 接口

struct gps_device_t {

 

    struct hw_device_t common;

 

 

 

    /**

 

     * Set the provided lights to the provided values.

 

     *

 

     * Returns: 0 on succes, error code on failure.

 

     */

 

    const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev);

 

};

 

 

 

22硬件适配层:

broadcom GPS硬件适配层的源码位于:/home/ls/Broadcom21553/hardware/broadcom/gps/allPartners/deliverables/middleware_connectors/unix/Android/gps_jni目录下。

 

gps_lcsapi.c中,定义了gps设备模块实例:

const struct hw_module_t HAL_MODULE_INFO_SYM = {

 

    .tag = HARDWARE_MODULE_TAG,

 

    .version_major = 1,

 

    .version_minor = 0,

 

    .id = GPS_HARDWARE_MODULE_ID,//JNI层从这个ID来调用HAL层接口

 

    .name = "lcsapi GPS Module",

 

    .author = "Broadcom Corporation",

 

    .methods = &hw_module_methods,

 

};

 

 

这里的methods指向该文件中的 hw_module_methods

static struct hw_module_methods_t hw_module_methods = {

 

    .open = open_gps

 

};

 

 

再看open_gps.

static int open_gps(const struct hw_module_t* module, char const* name,

 

                    struct hw_device_t** device)

 

{

 

LOGD("*****%s******start!\n", __func__);

 

    struct gps_device_t *gps_device = malloc(sizeof(struct gps_device_t));

 

    if (gps_device)

 

    {

 

        memset(gps_device, 0, sizeof(struct gps_device_t));

 

        gps_device->common.tag        = HARDWARE_DEVICE_TAG;

 

        gps_device->common.version    = 0;

 

        gps_device->common.module     = (struct hw_module_t*)module;

 

        gps_device->get_gps_interface = gps_get_hardware_interface;

 

 

 

        *device = (struct hw_device_t*)gps_device;

 

 

 

        return 0;

 

    }

 

 

 

    return 1;

 

LOGD("*****%s******done!\n", __func__);

 

}

 

 

此处可以看作是GPS设备的初始化函数,在使用设备前必须执行此函数。函数里面指定了hw_device_t module成员,以及gps_device_tget_gps_interface成员。上层可以通过gps_device_tget_gps_interface调用 gps_get_hardware_interface

 

gps_get_hardware_interface的定义如下:

#ifdef GPS_AS_MODULE

 

const GpsInterface* gps_get_hardware_interface(struct gps_device_t* dev)

 

#else

 

const GpsInterface* gps_get_hardware_interface(void)

 

#endif

 

{

 

LOGD("*****%s******start!\n", __func__);

 

        return &_GpsInterface;

 

LOGD("*****%s******done!\n", __func__);

 

}

 

 

 

22JNI适配层:

源码位于:/home/ls/Broadcom21553/frameworks/base/services/jni/com_android_server_location_GpsLocationProvider.cpp 

 

首先看注册JNI方法的函数定义:

int register_android_server_location_GpsLocationProvider(JNIEnv* env)

 

{

 

    return jniRegisterNativeMethods(env, "com/android/server/location/GpsLocationProvider", sMethods, NELEM(sMethods));

 

}

 

 

这个函数被同目录下的onload.cpp文件调用,调用地方在:

extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)

 

{

 

    JNIEnv* env = NULL;

 

    jint result = -1;

 

 

 

    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {

 

        LOGE("GetEnv failed!");

 

        return result;

 

    }

 

    LOG_ASSERT(env, "Could not retrieve the env!");

 

 

 

。。。。。。

    register_android_server_location_GpsLocationProvider(env);

 

 

 

    return JNI_VERSION_1_4;

 

}

 

 

从这里可以看到,JNI初始化的时候,即会进行JNI方法的注册,从而使上层应用能通过JNI调用c/c++本地方法。

 

回到register_android_server_location_GpsLocationProvider函数,变量sMethods定义如下:

static JNINativeMethod sMethods[] = {

 

     /* name, signature, funcPtr */

 

    {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},

 

    {"native_is_supported", "()Z", (void*)android_location_GpsLocationProvider_is_supported},

 

    {"native_init", "()Z", (void*)android_location_GpsLocationProvider_init},

 

    {"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup},

 

    {"native_set_position_mode", "(IIIII)Z", (void*)android_location_GpsLocationProvider_set_position_mode},

 

    {"native_start", "()Z", (void*)android_location_GpsLocationProvider_start},

 

    {"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop},

 

    {"native_delete_aiding_data", "(I)V", (void*)android_location_GpsLocationProvider_delete_aiding_data},

 

    {"native_read_sv_status", "([I[F[F[F[I)I", (void*)android_location_GpsLocationProvider_read_sv_status},

 

    {"native_read_nmea", "([BI)I", (void*)android_location_GpsLocationProvider_read_nmea},

 

    {"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time},

 

    {"native_inject_location", "(DDF)V", (void*)android_location_GpsLocationProvider_inject_location},

 

    {"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra},

 

    {"native_inject_xtra_data", "([BI)V", (void*)android_location_GpsLocationProvider_inject_xtra_data},

 

    {"native_agps_data_conn_open", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_agps_data_conn_open},

 

    {"native_agps_data_conn_closed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_closed},

 

    {"native_agps_data_conn_failed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_failed},

 

    {"native_agps_set_id","(ILjava/lang/String;)V",(void*)android_location_GpsLocationProvider_agps_set_id},

 

    {"native_agps_set_ref_location_cellid","(IIIII)V",(void*)android_location_GpsLocationProvider_agps_set_reference_location_cellid},

 

    {"native_set_agps_server", "(ILjava/lang/String;I)V", (void*)android_location_GpsLocationProvider_set_agps_server},

 

    {"native_send_ni_response", "(II)V", (void*)android_location_GpsLocationProvider_send_ni_response},

 

    {"native_agps_ni_message", "([BI)V", (void *)android_location_GpsLocationProvider_agps_send_ni_message},

 

    {"native_get_internal_state", "()Ljava/lang/String;", (void*)android_location_GpsLocationProvider_get_internal_state},

 

    {"native_update_network_state", "(ZIZLjava/lang/String;)V", (void*)android_location_GpsLocationProvider_update_network_state },

 

};

 

 

这里定义了GPS所有向上层提供的JNI本地方法,这些本地方法是如何与硬件适配层交互的呢?我们看其中一个本地方法 android_location_GpsLocationProvider_start

 

static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject obj)

 

{

 

    if (sGpsInterface)

 

        return (sGpsInterface->start() == 0);

 

    else

 

        return false;

 

}

 

 

这个sGpsInterface

android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz)

函数中调用

sGpsInterface = gps_device->get_gps_interface(gps_device);

 

生成。

 

23 JAVA Framework

该层的源码位于:/home/ls/Broadcom21553/frameworks/base/location下面:

 

231接口和类简介:

首先对GPS Framework重要的接口和类做一个简单的介绍:

接口:

GpsStatus.Listener:用于当Gps状态发生变化时接收通知

GpsStatus.NmeaListener: 用于接收GpsNMEA数据

LocationListener:用于接收当位置信息发生变化时,LocationManager发出的通知

类:

Address:地址信息类

Criteria:用于根据设备情况动态选择provider

Geocoder:用于处理地理编码信息

GpsSatellite:用于获取当前卫星状态

GpsStatus:用于获取当前Gps状态

Location:地理位置信息类

LocationManager:用于获取和操作gps系统服务

LocationProvider:抽象类,用于提供位置提供者

 

2,3.2 使用Gps编程接口:

下面用一个代码示例说明如何在应用层写一个简单的gps程序:

1,首先在AndroidManifest.xml中增加位置服务权限:

<uses-permission android:name="android.permission.INTERNET" />   

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />   

<uses-permission android:name="android.permission.ACCESS_FIND_LOCATION" />  

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>  

2,接着获取位置信息:

         //获取位置服务

 LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);  

        Criteria criteria = new Criteria();  

        // 获得最好的定位效果  

        criteria.setAccuracy(Criteria.ACCURACY_FINE);  //设置为最大精度

        criteria.setAltitudeRequired(false);  //不获取海拔信息

        criteria.setBearingRequired(false);  //不获取方位信息

        criteria.setCostAllowed(false);  //是否允许付费

        criteria.setPowerRequirement(Criteria.POWER_LOW);  // 使用省电模式

        // 获得当前的位置提供者  

        String provider = locationManager.getBestProvider(criteria, true);  

        // 获得当前的位置  

        Location location = locationManager.getLastKnownLocation(provider);  

Geocoder gc = new Geocoder(this);   

        List<Address> addresses = null;  

        try {

    //根据经纬度获得地址信息  

            addresses = gc.getFromLocation(location.getLatitude(), location.getLongitude(), 1);  

        } catch (IOException e) {  

            e.printStackTrace();  

        } if (addresses.size() > 0) {

//获取address类的成员信息

Sring msg = “”;   

        msg += "AddressLine" + addresses.get(0).getAddressLine(0)+ "\n";   

        msg += "CountryName" + addresses.get(0).getCountryName()+ "\n";   

        msg += "Locality" + addresses.get(0).getLocality() + "\n";   

        msg += "FeatureName" + addresses.get(0).getFeatureName();   

        }   

 

3,设置帧听,当位置信息发生变化时,自动更新相关信息:

       //匿名类,继承自LocationListener接口

private final LocationListener locationListener = new LocationListener() {

            public void onLocationChanged(Location location) {

            updateWithNewLocation(location);//更新位置信息

            }

            public void onProviderDisabled(String provider){

            updateWithNewLocation(null);//更新位置信息

            }

            public void onProviderEnabled(String provider){ }

            public void onStatusChanged(String provider, int status,Bundle extras){ }

    };

//更新位置信息

private void updateWithNewLocation(Location location) {

        

 

            if (location != null) {

//获取经纬度

            double lat = location.getLatitude();

            double lng = location.getLongitude();

    }

//添加侦听

 locationManager.requestLocationUpdates(provider, 2000, 10,locationListener);

 

23.3接口和类分析:

LocationManger的代码文件位于/home/ls/Broadcom21553/frameworks/base/location/java/android/location/LocationManager.java

我们看其构造函数:

 public LocationManager(ILocationManager service) {

 

     mService = service;

 

 }

 

其中mServiceILoctionManager接口类型,其构造函数的参数为service,外部调用时传入LocationManager Service示例。一般由getSystemService获得LocationManagerService服务,再强制转换为LocationManager

 

如上面代码示例:

LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);  //就是这样获取gps服务的。

 

这里的这里的Context.LOCATION_SERVICE”location”,标识gps服务

 

LocationManagerService服务是整个GpsFramework的核心,首先看它是如何被加载的,代码位于:

/home/ls/Broadcom21553/frameworks/base/services/java/com/android/server/SystemServer.java

 

…//省略其他代码

LocationManagerService location = null;

…//省略其他代码

try {

                Slog.i(TAG, "Location Manager");

                location = new LocationManagerService(context);

                ServiceManager.addService(Context.LOCATION_SERVICE, location);

            } catch (Throwable e) {

                Slog.e(TAG, "Failure starting Location Manager", e);

            }

 

此处向SystemManager系统服务管理器注册了新的服务,其名称为location”,类型为LocationManagerService。注册此服务后,Java应用程序就可以通过ServiceManager获得LocationManagerService的代理接口ILocationManager.Stub,从而调用LocationManagerServce提供的接口函数。

IlocationManager位于:

/home/ls/Broadcom21553/frameworks/base/location/java/android/location

/ILocationManager.aidl 

/**

 * System private API for talking with the location service.

 *

 * {@hide}

 */

interface ILocationManager

{

    List<String> getAllProviders();

    List<String> getProviders(in Criteria criteria, boolean enabledOnly);

    String getBestProvider(in Criteria criteria, boolean enabledOnly);

    boolean providerMeetsCriteria(String provider, in Criteria criteria);

 

    void requestLocationUpdates(String provider, in Criteria criteria, long minTime, float minDistance,

        boolean singleShot, in ILocationListener listener);

    void requestLocationUpdatesPI(String provider, in Criteria criteria, long minTime, float minDistance,

        boolean singleShot, in PendingIntent intent);

    void removeUpdates(in ILocationListener listener);

    void removeUpdatesPI(in PendingIntent intent);

 

    boolean addGpsStatusListener(IGpsStatusListener listener);

    void removeGpsStatusListener(IGpsStatusListener listener);

 

    // for reporting callback completion

    void locationCallbackFinished(ILocationListener listener);

 

    boolean sendExtraCommand(String provider, String command, inout Bundle extras);

 

    void addProximityAlert(double latitude, double longitude, float distance,

        long expiration, in PendingIntent intent);

    void removeProximityAlert(in PendingIntent intent);

 

    Bundle getProviderInfo(String provider);

    boolean isProviderEnabled(String provider);

 

    Location getLastKnownLocation(String provider);

 

    // Used by location providers to tell the location manager when it has a new location.

    // Passive is true if the location is coming from the passive provider, in which case

    // it need not be shared with other providers.

    void reportLocation(in Location location, boolean passive);

 

    boolean geocoderIsPresent();

    String getFromLocation(double latitude, double longitude, int maxResults,

        in GeocoderParams params, out List<Address> addrs);

    String getFromLocationName(String locationName,

        double lowerLeftLatitude, double lowerLeftLongitude,

        double upperRightLatitude, double upperRightLongitude, int maxResults,

        in GeocoderParams params, out List<Address> addrs);

 

    void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite,

        boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,

        boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy);

    void removeTestProvider(String provider);

    void setTestProviderLocation(String provider, in Location loc);

    void clearTestProviderLocation(String provider);

    void setTestProviderEnabled(String provider, boolean enabled);

    void clearTestProviderEnabled(String provider);

    void setTestProviderStatus(String provider, int status, in Bundle extras, long updateTime);

    void clearTestProviderStatus(String provider);

 

    // for NI support

    boolean sendNiResponse(int notifId, int userResponse);

}

 

android系统通过ILocationManager.aidl文件自动生成ILocationManager.Stub代理接口,在Java应用程序中哦搞获取LocationManagerService的方式如下:

ILocationManager mLocationManager;

IBinder b = ServiceManager.getService(Context.LOCATION_SERVICE);

mLocationManager = IlocationManager.Stub.asInterface(b);

 

客户端通过mLocationManager即可操作LocationMangerService继承自ILocationManager.Stub的的公共接口。之前提到了通过getSystemSerivice方式也可以获得LocationManagerService,但getSystemService()返回的是Object,必须转换为其他接口,我们可以看到之前的是强制转换为LocationManager类型,而此处由ServiceManager.getService返回IBinder接口,再通过ILocationManager.Stub转换为ILocationManager类型,是更加规范的做法。

 

LocationManagerServce的代码文件位于:

/home/ls/Broadcom21553/frameworks/base/services/java/com/android/server/LocationManagerService.java 

 

我们首先看其中的systemReady()函数:

void systemReady() {

 

    // we defer starting up the service until the system is ready 

 

    Thread thread = new Thread(null, this, "LocationManagerService");

 

    thread.start();

 

}

 

 

此处启动自身的服务线程,当启动此线程后,会运行run()函数:

  public void run()

 

  {

 

      Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

 

      Looper.prepare();

 

      mLocationHandler = new LocationWorkerHandler();

 

      initialize();

 

      Looper.loop();

 

  }

 

 

此处调用了initialize();

进行初始化,

private void initialize() {

       //...省略其他代码

        loadProviders();

//...省略其他代码

        

    }

此处调用了loadProviders()函数,loadProvider()函数调用了loadProvidersLocked()

->调用_loadProvidersLocked()

代码如下:

private void _loadProvidersLocked() {

        // Attempt to load "real" providers first

        if (GpsLocationProvider.isSupported()) {

            // Create a gps location provider

            GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);

            mGpsStatusProvider = gpsProvider.getGpsStatusProvider();

            mNetInitiatedListener = gpsProvider.getNetInitiatedListener();

            addProvider(gpsProvider);

            mGpsLocationProvider = gpsProvider;

        }

 

        // create a passive location provider, which is always enabled

        PassiveProvider passiveProvider = new PassiveProvider(this);

        addProvider(passiveProvider);

        mEnabledProviders.add(passiveProvider.getName());

 

        // initialize external network location and geocoder services

        if (mNetworkLocationProviderPackageName != null) {

            mNetworkLocationProvider =

                new LocationProviderProxy(mContext, LocationManager.NETWORK_PROVIDER,

                        mNetworkLocationProviderPackageName, mLocationHandler);

            addProvider(mNetworkLocationProvider);

        }

 

        if (mGeocodeProviderPackageName != null) {

            mGeocodeProvider = new GeocoderProxy(mContext, mGeocodeProviderPackageName);

        }

 

        updateProvidersLocked();

    }

 

我们再看下GpsLocationProvider的实现frameworks/base/services/java/com/android/server/location/GpsLocationProvider.java

 

gpsLocationProvider的构造函数中:

public GpsLocationProvider(Context context, ILocationManager locationManager) {

       

//...省略部分代码

        IntentFilter intentFilter = new IntentFilter();

        intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);

        intentFilter.addDataScheme("sms");

        intentFilter.addDataAuthority("localhost","7275");

        context.registerReceiver(mBroadcastReciever, intentFilter);

 

        intentFilter = new IntentFilter();

        intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);

        try {

            intentFilter.addDataType("application/vnd.omaloc-supl-init");

        } catch (IntentFilter.MalformedMimeTypeException e) {

            Log.w(TAG, "Malformed SUPL init mime type");

        }

        context.registerReceiver(mBroadcastReciever, intentFilter);

 

        

        //...省略部分代码

        // wait until we are fully initialized before returning

        mThread = new GpsLocationProviderThread();

        mThread.start();

        while (true) {

            try {

                mInitializedLatch.await();

                break;

            } catch (InterruptedException e) {

                Thread.currentThread().interrupt();

            }

        }

    }

 

这里注册了广播接受者mBroadcastReciever,用于接收广播消息,消息过滤在intentFilter中定义。下面是它接收广播消息时的动作:

private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {

        @Override public void onReceive(Context context, Intent intent) {

            String action = intent.getAction();

 

            if (action.equals(ALARM_WAKEUP)) {

                if (DEBUG) Log.d(TAG, "ALARM_WAKEUP");

                startNavigating(false);

            } else if (action.equals(ALARM_TIMEOUT)) {

                if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");

                hibernate();

            } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {

                checkSmsSuplInit(intent);

            } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {

                checkWapSuplInit(intent);

             }

        }

    };

 

当接收ALARM_EAKEUP时,执行startNavigating函数,当接收到ALARM_TIMEOUT广播时,执行hibernate函数。这两个函数很关键,下面看他们的实现:

private void startNavigating(boolean singleShot) {

        

//...省略部分代码

            

            if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,

                    interval, 0, 0)) {

                mStarted = false;

                Log.e(TAG, "set_position_mode failed in startNavigating()");

                return;

            }

            if (!native_start()) {

                mStarted = false;

                Log.e(TAG, "native_start failed in startNavigating()");

                return;

            }

//...省略部分代码

    }

 

看到没有,这里调用了native_set_position_modenative_start方法,而这些方法正是我们之前在JNI适配层提到的注册的本地方法。

 

 

下面回到LocationManagerService,分析如何获取最新的位置信息(Location),获取最新的location的函数是getLastKnownLocation,其实现如下:

private Location _getLastKnownLocationLocked(String provider) {

        checkPermissionsSafe(provider);

 

        LocationProviderInterface p = mProvidersByName.get(provider);

        if (p == null) {

            return null;

        }

 

        if (!isAllowedBySettingsLocked(provider)) {

            return null;

        }

 

        return mLastKnownLocation.get(provider);

    }

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值