Android系统Gps开发

Gps  (global   Position  System 全球定位系统)和定位部分

除此之外还有利用基站(cell)定位的AGPS等设备

 定们系列统的基本架构

 主要数据来源有两个: GPS定位和network定位(基于cellwifi热点的定位)

定位部分的结构如图

  定位系统的驱动层

 Network定位的底层驱动和适配层实际上就是RILwifi框架的组成部分

 Cell定位就是利用基站的cellID以及LAC实现

 Wifi则是利用热点的相关信息 如名字 mac地址 ip地址实现

 GPS 设备分为硬GPS 和软GPS 

   硬GPS上电就可以直接输出NMEA 数据

   软GPS需要主控芯片控制其运行状态,需要主控方进行计算才能得到NMEA数据

 GPS本地实现

GPS的本地实现部分主要是GPS适配层,头文件的路径为:\hardware\libhardware\include\hardware

该目录下的gps.h提供了JNI层调用的接口,该文件定义的常量,包括位置模式、状态值、定位标志、帮助数据

//定义了标准GPS接口的结构体

typedef struct {

    /** set to sizeof(GpsInterface) */

    size_t          size;

    /**

     * Opens the interface and provides the callback routines

     * to the implemenation of this interface.

        初始化GPS,设置回调函数

     */

    int   (*init)( GpsCallbacks* callbacks );

/** Starts navigating. */ 

//开始导航

    int   (*start)( void );

/** Stops navigating. */

//停止导航

    int   (*stop)( void );

/** Closes the interface. */

//关闭接口

    void  (*cleanup)( void );

/** 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);

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

//获得扩展消息的指针

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

} GpsInterface;

//表示GPS的定位信息

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. */

     //WGS84坐标系统表示的高度信息

    double          altitude;

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

//速度  m/s

    float           speed;

/** Represents heading in degrees. */

//表示方向

    float           bearing;

/** Represents expected accuracy in meters. */

//表示精度

    float           accuracy;

/** Timestamp for the location fix. */

//表示时间戮

    GpsUtcTime      timestamp;

} GpsLocation;

当上层调用:GpsInterface.init时,会调用一个gpscallbacks结构指针,注册到适配层

//位置信息的回调函数

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

// 状态信息的回调函数

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

//SV状态信息的回调函数

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

  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;

GPS的部分源代码路径为:\hardware\qcom\gps

GPS组件的目标文件是;libhardware_legacy.so

Gps_qemu.c文件是基于模拟器环境的GPS适配层,在编写特定的GPS 适配层时,可以以gps_quemu.c中的大部分处理流程作为基础进行改写,它实现了一套NMEA解析机制,以及gps.h中的gpsInterface接口,

gpsInterface 接口比较简单,包括启动/停止和上报频率等接口,

NEMA解析是核心,是基于文本块的算法

因为是模拟,所以NMEA数据需要从一个socket接口gps_fd传输进来.  在独立线程中进行解析

NMEA数据最终会解析成gps.h中定义的gpsLocation的格式

GPS 部分JNI的实现

代码的路径为:\frameworks\base\services\jni\com_android_server_location_GpsLocationProvider.cpp

JNI层直接与GPS驱动层打交道,它访问适配层定义的GpaInterface 实现自已的gpscallbacksGPS适配层调用

部分代码如下:

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,

};

JNI实现了一个native_wait_for_event函数,上层如果需要获得消息,则在独立线程中调用此函数阻塞

如果上层有NMEA解析完成并回调,通过线程同步机制,使等待的native_wait_for_event的线程取得上报数据,完成一次数据上报

Xtra是部分增强型GPS的机制,可以提前从网上下载数据

定位系统的java实现

代码路径为:\frameworks\base\location\java\android\location

ILocationManagerandroid 定们系统的核心

LocationServiceManager是定位系统的服务器端,它在目录:\frameworks\base\services\java\com\android\server下

LocationProviderProxy mNetworkLocationProvider;

     LocationProviderInterface mGpsLocationProvider;

**************************************************************

2.3中的变化

**************************************************************

\frameworks\base\services\java\com\android\server\location目录下的GpsLocationProvider.java它直接继承

LocationProviderInterface(23之前可能是LocationProviderImpl), 它提供了底层的控制接口,同时开启一个gpsEventThread通过轮询native_wait_for_event来取得底层上报的数据

App发出定位申请,启动定位服务线程,此线程会在APP framwork中调用location provider

通过被native方法调用到JNI, JNI获得gpsInterface并传给接口一个回调函数的实现

gpsInterface就是HAL层最主要的实现

 

上层实现的思路

1、获取GPSLocation Provider

 2、将此Provider传入到requestLocationUpdates()方法,让Android系统获知搜索位置方式。

 3、创建实现了GpsStatus.Listener接口的对象,重写onGpsStatusChanged()方法,向LocationManager添加次监听器,检测卫星状态。(可选步骤)

Android GPS 架构分析

Framework 

 代码路径为:

1 \frameworks\base\location\java\android\location

 供api调用

 2 frameworks\base\location\java\com\android\internal\location

 这个目录是frameworklocation服务的内部实现

3 \frameworks\base\services\java\com\android\server

  这是location服务对内部实现的一个封装

JNI层:

 代码路径:

22版本中

frameworks/base/core/jni/android_location_GpsLocationProvider.cpp

2.3版式本中

\frameworks\base\services\jni\com_android_server_location_GpsLocationProvider.cpp

上层承接freanwork,下层调用HAL

HAL硬件抽象层

代码路径

 2.3 

 \hardware\libhardware\include\hardware

/framework/base/services/jni/com_android_server_location_GpsLocationProvider.cpp

 相当于linux应用程序的一个接口,直接操作硬件设备

底层几个重要和数据结构

1 gpsInterface 是最重要的数据结构,它是底层实现的接口,如果要porting到自已的板子上,就要实现这这些接口,

  该接口的定义在gps.h,模拟器实现在gps_qemu.c

 typedef struct {   

    size_t          size;    

    int   (*init)( GpsCallbacks* callbacks );

        int   (*start)( void );

        int   (*stop)( void );

    void  (*cleanup)( void );

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

                         int uncertainty);

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

    void  (*delete_aiding_data)(GpsAidingData flags);   

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

            uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);

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

} GpsInterface;

2 gpscallbacks回调函数结构体,定义同上,实现在com_android_server_android_location_GpsLocationProvider.cpp

typedef struct {

    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;

    //以下几个回调函数是在2.3以后添加的回调函数

    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;

3 Gpslocation表示loaction数据信息 2.32.2多了个size属性

typedef struct {

    //2.3之后添加

      size_t          size; 

    uint16_t        flags;    

    double          latitude;  

    double          longitude;   

    double          altitude; 

    float           speed;   

    float           bearing;  

    float           accuracy;   

    GpsUtcTime      timestamp;

} GpsLocation;

Gps的定位服务(locationManager)的启动过程

LocationManager这项服务是systemServer.java 来启动,也就是在系统启动之后就启动

systemServer.java [framework/base/services/java/com/android/server] 

public static final void init2() {

Slog.i(TAG, "Entered the Android system server!"); 

Thread thr = new ServerThread(); 

thr.setName("android.server.ServerThread"); 

thr.start(); 

}

ServerThread线程的run函数中LocationManager服务的代码段如下: 

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); 

}

run函数的后半部分,是服务对系统的反馈,就是systemReady()函数。 LocationManager服务的反馈函数如下:

final LocationManagerService locationF = location;

其中的locationF LocationManagerServicefinal类型,就是一旦赋值,不能更改。

if (locationF != null) locationF.systemReady();

LocationManagerService代码路径如下:\frameworks\base\services\java\com\android\server

构造器如下:

   public LocationManagerService(Context context) {

        super();

        mContext = context;

        Resources resources = context.getResources();

        mNetworkLocationProviderPackageName = resources.getString(

                com.android.internal.R.string.config_networkLocationProvider);

        mGeocodeProviderPackageName = resources.getString(

                com.android.internal.R.string.config_geocodeProvider);

        mPackageMonitor.register(context, true);

        if (LOCAL_LOGV) {

            Slog.v(TAG, "Constructed LocationManager Service");

        }

    }

void systemReady() {

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

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

        thread.start();

    }

 在run函数中,又调用了initialize 函数

 public void run()

    {

        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

        Looper.prepare();

        mLocationHandler = new LocationWorkerHandler();

        initialize();//************************

        Looper.loop();

    }

  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);

        mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mLocationHandler);

        SettingsObserver settingsObserver = new SettingsObserver();

        mSettings.addObserver(settingsObserver);

    }

初始化函数中,最重要的便是 loadProviders()函数。

private void loadProviders() {

        synchronized (mLock) { 

            if (sProvidersLoaded) { 

                return; 

            } 

            // Load providers

            loadProvidersLocked(); 

            sProvidersLoaded = true; 

        } 

    }

 

 private void loadProvidersLocked() {

        try {

            _loadProvidersLocked();

        } catch (Exception e) {

            Slog.e(TAG, "Exception loading providers:", e);

        }

}

_loadProvidersLocked函数

 private void _loadProvidersLocked() {

        // Attempt to load "real" providers first

        //取得GPS的接口

        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.isSupported()得到了HAL层的GPS接口gpsInterface

调用到gps.cpp[hardware/libhardware_legacy/gps]中的gps_get_interface()

GpsLocationProvider的路径为:\frameworks\base\services\java\com\android\server\location

 部分代码如下:

   public static boolean isSupported() {

        //调用的是本地方法

        return native_is_supported();

    }

函数中只有一句话, 这调用了native方法,既Jni层定义的方法。native_is_supported对应在

framework/base/services/jni/com_android_server_location_GpsLocationProvider.cpp文件中的android_location_GpsLocationProvider_is_supported方法。

 部分代码如下;

static jboolean android_location_GpsLocationProvider_is_supported(JNIEnv* env, jclass clazz) {

    return (sGpsInterface != NULL || get_gps_interface() != NULL);

}

get_gps_interface()的具体代码如下:

static const GpsInterface* get_gps_interface() {

    int err;

    hw_module_t* module;

    const GpsInterface* interface = NULL;

    err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);

    if (err == 0) {

        hw_device_t* device;

        err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);

        if (err == 0) {

            gps_device_t* gps_device = (gps_device_t *)device;

            interface = gps_device->get_gps_interface(gps_device);

        }

    }

    return interface;

}

 get_gps_interface去打开模组,之后打开设备,然后通过设备区调用HAL层中的get_gps_interfacegps_device

gps.c(代码路径为:\hardware\qcom\gps\loc_api\libloc_api)中实现的gps__get_gps_interfacey调用了loc_eng.cpp

gps.c部分代码如下:

const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev)

{

    return get_gps_interface();

}

loc_eng.cpp的部分代码如下:

static const GpsInterface sLocEngInterface =

{

    sizeof(GpsInterface),

    loc_eng_init,

    loc_eng_start,

    loc_eng_stop,

    loc_eng_cleanup,

    loc_eng_inject_time,

    loc_eng_inject_location,

    loc_eng_delete_aiding_data,

    loc_eng_set_position_mode,

    loc_eng_get_extension,

};

经过以的操作我们就获得了GPS的接口locationManagerService.java,如果找到了硬件,并取得了接口后,接着执行下一句

 GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);

GpsLocationProvider的代码路径为:frameworks\base\services\java\com\android\server\location

 public GpsLocationProvider(Context context, ILocationManager locationManager) {

        mContext = context;

        //mLocationManager就是第二个参数.也就是locationManagerService

        mLocationManager = locationManager;

        mNIHandler = new GpsNetInitiatedHandler(context);

        mLocation.setExtras(mLocationExtras);

....................

}

_loadProvidersLocked函数,在构造完成后,将其add到全局变量ArrayList<LocationProviderInterface> mProviders中,备以后调用.

接着启动了两个线程,但是可惜的是这两个服务都无法启动,因为他们是通过配置文件conifg.xml 得到服务的名字,然后启动服务的。但是在这个配置文件中,两个服务的名字都是null

配置文件的路径为;framework/base/core/res/res/values

部分代码如下:

<!-- Component name of the service providing network location support. -->

    <string name="config_networkLocationProvider">@null</string>

    <!-- Component name of the service providing geocoder API support. -->

    <string name="config_geocodeProvider">@null</string>

这就是为什么在调用getFromLocationName和 getFromLocation时会提示service not available,2.2就存在的bug

_loadProvidersLocked函数的最后调用的是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));

        }

    }

mProviders里面应该存在一个gpsProvider PassiveProvider,而gpsProvider是未被enable的。而passiveProviderenable的。

这边我们对gpsProvider进行讨论,他执行的是updateProviderListenersLockedname,true) 然后当有发生改变,就是changesMade=true时,它发送了广播,内容是告诉大家LocationManager发生了变化,让需要的接收者自己接收。 

 updateProviderListenersLocked(name, false)函数的部分代码如下:

    private void updateProviderListenersLocked(String provider, boolean enabled) {

        int listeners = 0;

        LocationProviderInterface p = mProvidersByName.get(provider);

        if (p == null) {

            return;

        }

        ArrayList<Receiver> 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 receiver

                if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {

                    if (deadReceivers == null) {

                        deadReceivers = new ArrayList<Receiver>();

                    }

                    deadReceivers.add(record.mReceiver);

                }

                listeners++;

            }

        }

        if (deadReceivers != null) {

            for (int i=deadReceivers.size()-1; i>=0; i--) {

                removeUpdatesLocked(deadReceivers.get(i));

            }

        }

        //如果为真则启动gas

        if (enabled) {

            p.enable();

            if (listeners > 0) {

                p.setMinTime(getMinTimeLocked(provider), mTmpWorkSource);

                p.enableLocationTracking(true);

            }

        } else {

            p.enableLocationTracking(false);

            p.disable();

        }

    }

if(enable)中,如果enable 为真,则启动GPS,调用p.enable()方法,该方法的实现是在

GpsLocationProvider.java类中他继承了LocationProviderInterface

代码路径为:\frameworks\base\services\java\com\android\server\location

部分代码如下:

   public void enable() {

        synchronized (mHandler) {

            sendMessage(ENABLE, 1, null);

        }

    }

 

   //每次进入此消息,就是清除之前所有消息发送消息交给handlerMassage处理

  private void sendMessage(int message, int arg, Object obj) {

        // hold a wake lock while messages are pending

        synchronized (mWakeLock) {

            mPendingMessageBits |= (1 << message);

            mWakeLock.acquire();

            mHandler.removeMessages(message);

            Message m = Message.obtain(mHandler, message);

            m.arg1 = arg;

            m.obj = obj;

            mHandler.sendMessage(m);

        }

    }

handlerMessage 中的处理调用handleEnable();

 public void handleMessage(Message msg) {

            int message = msg.what;

            switch (message) {

                case ENABLE:

                    if (msg.arg1 == 1) {

                        handleEnable();

                    } else {

                        handleDisable();

                    }

                    break;

       }

      handleEnable 主要作了两件事,

        1 调用本地方法 native_init(),初始化gps

         本地方法的具体实现是在com_android_server_location_GpsLocationProvider.cpp,

          部分内容为下:

           static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj)

{

    //取得接口,并初始化gps 

    const GpsInterface* interface = GetGpsInterface(env, obj);

    if (!interface)

        return false;

    if (!sGpsDebugInterface)

       sGpsDebugInterface = (const   GpsDebugInterface*)interface->get_extension(GPS_DEBUG_INTERFACE);

    return true;

}

        2 试图启动AGPS服务

   代码如下:

 private void handleEnable() {

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

        if (mEnabled) return;

        //调用本地方法初始化GPS

        mEnabled = native_init();

        

        //试图启动AGPS服务

        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");

        }

    }

取得接口的方法中,也调用了 get_gps_interface

代码如下:

static const GpsInterface* GetGpsInterface(JNIEnv* env, jobject obj) {

    // this must be set before calling into the HAL library

    if (!mCallbacksObj)

        mCallbacksObj = env->NewGlobalRef(obj);

    if (!sGpsInterface) {

        sGpsInterface = get_gps_interface();

        if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0) {

            sGpsInterface = NULL;

            return NULL;

        }

    }

    return sGpsInterface;

}

Gps_qemu.c的代码路径为:\sdk\emulator\gps

这边qemu_gps_init函数即是sGpsInterface->init函数,其中里面做了gps_state_init初始化,并注册了callbacks回调函数,而这个函数也是在JNI层实现的,而且有JNI层传下来的函数。

部分代码为;

qemu_gps_init(GpsCallbacks* callbacks)

{

    GpsState*  s = _gps_state;

    if (!s->init)

        gps_state_init(s);

    if (s->fd < 0)

        return -1;

    s->callbacks = *callbacks;

    return 0;

}

在这个主方法中首先打开串口,然后进立socket通信,然后建立线程监听底层数据上报

static void

gps_state_init( GpsState*  state )

{

    state->init       = 1;

    state->control[0] = -1;

    state->control[1] = -1;

    state->fd         = -1;

    state->fd = qemud_channel_open(QEMU_CHANNEL_NAME);

    if (state->fd < 0) {

        D("no gps emulation detected");

        return;

    }

    D("gps emulation will read from '%s' qemud channel", QEMU_CHANNEL_NAME );

    if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, state->control ) < 0 ) {

        LOGE("could not create thread control socket pair: %s", strerror(errno));

        goto Fail;

    }

    if ( pthread_create( &state->thread, NULL, gps_state_thread, state ) != 0 ) {

        LOGE("could not create gps thread: %s", strerror(errno));

        goto Fail;

    }

    D("gps state initialized");

    return;

Fail:

    gps_state_done( state );

}

该方法说明在初始化时调用的相关扩展接口是没用的

static const void*

qemu_gps_get_extension(const char* name)

{

    // no extensions supported

    return NULL;

}

22的时候handlerEnable还创建了一个监听线程

而在2.3GpsLocationProvider(路径为:frameworks\base\services\java\com\android\server\location

在构造函数中就创建了这个 监听线程

构造器中的部分代码

 mThread = new GpsLocationProviderThread();

        mThread.start();

        while (true) {

            try {

                mInitializedLatch.await();

                break;

            } catch (InterruptedException e) {

                Thread.currentThread().interrupt();

            }

        }

//run函数的部分内容

//initialize初始化函数,然后新建一个looper,新建一个providerHandler 用于处理该线程的消息

private final class GpsLocationProviderThread extends Thread {

        public GpsLocationProviderThread() {

            super("GpsLocationProvider");

        }

        public void run() {

            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

            initialize();

            Looper.prepare();

            mHandler = new ProviderHandler();

            // signal when we are initialized and ready to go

            mInitializedLatch.countDown();

            Looper.loop();

        }

}

  private void initialize() {

        // register our receiver on our thread rather than the main thread

        IntentFilter intentFilter = new IntentFilter();

        intentFilter.addAction(ALARM_WAKEUP);

        intentFilter.addAction(ALARM_TIMEOUT);

        mContext.registerReceiver(mBroadcastReciever, intentFilter);

    }

初始化主要是将线程的接收者注册到我们的线程上,而不是注册到主线程上。

到这边为止我们完成了 p.enable()函数的分析。

locationManagerService.java,run ()---> initialize()--->loadProviders()----->loadProvidersLocked()

------->_loadProvidersLocked()------->updateProvidersLocked()------>updateProviderListenersLocked0

-------->调用到以下方法

private void updateProviderListenersLocked(String provider, boolean enabled) {

        int listeners = 0;

        LocationProviderInterface p = mProvidersByName.get(provider);

        if (p == null) {

            return;

        }

        ArrayList<Receiver> 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 receiver

                if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {

                    if (deadReceivers == null) {

                        deadReceivers = new ArrayList<Receiver>();

                    }

                    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();

        }

    }

enableLocationTracking在gpsLocationProvider.java

  public void enableLocationTracking(boolean enable) {

        // FIXME - should set a flag here to avoid race conditions with single shot request

        synchronized (mHandler) {

            sendMessage(ENABLE_TRACKING, (enable ? 1 : 0), null);

        }

    }

  private void sendMessage(int message, int arg, Object obj) {

        // hold a wake lock while messages are pending

        synchronized (mWakeLock) {

            mPendingMessageBits |= (1 << message);

            mWakeLock.acquire();

            mHandler.removeMessages(message);

            Message m = Message.obtain(mHandler, message);

            m.arg1 = arg;

            m.obj = obj;

            mHandler.sendMessage(m);

        }

    }

  private final class ProviderHandler extends Handler {

        @Override

        public void handleMessage(Message msg) {

            int message = msg.what;

            switch (message) {

                case ENABLE:

                    if (msg.arg1 == 1) {

                        handleEnable();

                    } else {

                        handleDisable();

                    }

                    break;

                case ENABLE_TRACKING:

                     //

                     handleEnableLocationTracking(msg.arg1 == 1);

                    break;

}

       }

   }

handleEnableLocationTracking 函数

 private void handleEnableLocationTracking(boolean enable) {

        if (enable) {

            mTTFF = 0;

            mLastFixTime = 0;

            startNavigating(false);

        } else {

            if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {

                mAlarmManager.cancel(mWakeupIntent);

                mAlarmManager.cancel(mTimeoutIntent);

            }

            stopNavigating();

        }

    }

startNavigating方法   开始导航

 代码如下:

private void startNavigating(boolean singleShot) {

        if (!mStarted) {

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

            mStarted = true;

            mSingleShot = singleShot;

            mPositionMode = GPS_POSITION_MODE_STANDALONE;

             if (Settings.Secure.getInt(mContext.getContentResolver(),

                    Settings.Secure.ASSISTED_GPS_ENABLED, 1) != 0) {

                if (singleShot && hasCapability(GPS_CAPABILITY_MSA)) {

                    mPositionMode = GPS_POSITION_MODE_MS_ASSISTED;

                } else if (hasCapability(GPS_CAPABILITY_MSB)) {

                    mPositionMode = GPS_POSITION_MODE_MS_BASED;

                }

            }

            int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);

            //本地方法

            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;

            }

            // reset SV count to zero

            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);

            mFixRequestTime = System.currentTimeMillis();

            if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {

                // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT

                // and our fix interval is not short

                if (mFixInterval >= NO_FIX_TIMEOUT) {

                    mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,

                            SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);

                }

            }

        }

    }

在开启导航的这个方法中 ,调用的两个重要的本地方法

 这两个本地方法可以在 com_android_server_location_GpsLocationProvider.cpp这个文件中找到

1 native_set_position_mode

实现代码如下:

static jboolean android_location_GpsLocationProvider_set_position_mode(JNIEnv* env, jobject obj,

        jint mode, jint recurrence, jint min_interval, jint preferred_accuracy, jint preferred_time)

{

    const GpsInterface* interface = GetGpsInterface(env, obj);

    if (interface)

        //这里调用了接口的set_position_mode方法

        return (interface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy,

                preferred_time) == 0);

    else

        return false;

}

 该方法调用了接口的set_position_mode方法,这个方法的实现在(模拟器)的相关类中可以看到期实现

部分代码如下;

static int qemu_gps_set_position_mode(GpsPositionMode mode, int fix_frequency)

{

    // FIXME - support fix_frequency

    return 0;

}

2  native_start 通过向底层发送命令来启动GPS,  这个底层就是enable/init函数中启动的等待数据的线程 

static int

qemu_gps_start()

{

    GpsState*  s = _gps_state;

    if (!s->init) {

        D("%s: called with uninitialized state !!", __FUNCTION__);

        return -1;

    }

    D("%s: called", __FUNCTION__);

    gps_state_start(s);

    return 0;

}

static void  gps_state_start( GpsState*  s )

{

    char  cmd = CMD_START;

    int   ret;

    do { ret=write( s->control[0], &cmd, 1 ); }

    while (ret < 0 && errno == EINTR);

    if (ret != 1)

        D("%s: could not send CMD_START command: ret=%d: %s",

          __FUNCTION__, ret, strerror(errno));

}

   数据监听线程

static void*   gps_state_thread( void*  arg )

{

    GpsState*   state = (GpsState*) arg;

    NmeaReader  reader[1];

    int         epoll_fd   = epoll_create(2);

    int         started    = 0;

    int         gps_fd     = state->fd;

    int         control_fd = state->control[1];

    nmea_reader_init( reader );

    // register control file descriptors for polling

    epoll_register( epoll_fd, control_fd );

    epoll_register( epoll_fd, gps_fd );

    D("gps thread running");

    // now loop

    for (;;) {

        struct epoll_event   events[2];

        int                  ne, nevents;

        nevents = epoll_wait( epoll_fd, events, 2, -1 );

        if (nevents < 0) {

            if (errno != EINTR)

                LOGE("epoll_wait() unexpected error: %s", strerror(errno));

            continue;

        }

        D("gps thread received %d events", nevents);

        for (ne = 0; ne < nevents; ne++) {

            if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0) {

                LOGE("EPOLLERR or EPOLLHUP after epoll_wait() !?");

                goto Exit;

            }

            if ((events[ne].events & EPOLLIN) != 0) {

                int  fd = events[ne].data.fd;

                if (fd == control_fd)

                {

                    char  cmd = 255;

                    int   ret;

                    D("gps control fd event");

                    do {

                        ret = read( fd, &cmd, 1 );

                    } while (ret < 0 && errno == EINTR);

                    if (cmd == CMD_QUIT) {

                        D("gps thread quitting on demand");

                        goto Exit;

                    }

                    else if (cmd == CMD_START) {

                        if (!started) {

                            D("gps thread starting  location_cb=%p", state->callbacks.location_cb);

                            started = 1;

                            nmea_reader_set_callback( reader, state->callbacks.location_cb );

                        }

                    }

                    else if (cmd == CMD_STOP) {

                        if (started) {

                            D("gps thread stopping");

                            started = 0;

                            nmea_reader_set_callback( reader, NULL );

                        }

                    }

                }

                else if (fd == gps_fd)

                {

                    char  buff[32];

                    D("gps fd event");

                    for (;;) {

                        int  nn, ret;

                        ret = read( fd, buff, sizeof(buff) );

                        if (ret < 0) {

                            if (errno == EINTR)

                                continue;

                            if (errno != EWOULDBLOCK)

                                LOGE("error while reading from gps daemon socket: %s:", strerror(errno));

                            break;

                        }

                        D("received %d bytes: %.*s", ret, ret, buff);

                        for (nn = 0; nn < ret; nn++)

                            nmea_reader_addc( reader, buff[nn] );

                    }

                    D("gps fd event end");

                }

                else

                {

                    LOGE("epoll_wait() returned unkown fd %d ?", fd);

                }

            }

        }

    }

Exit:

    return NULL;

}

 这个监听线程最主要的一个就是nmea_reader_set_callback( )函数

其实就是注册了一个回调函数,location_cb 这个回调函数就是对底层location数据上报的回调函数。

到此 

enableLocationTracking函数完成了,

也就是LocationManageService.java

updateProviderListenersLocked的完成 

也就是updateProvidersLocked的完成,

也就是loadProviders函数的完成 

也就是 initialize的完成,

也就是run的完成,

也就是systemReady的完成

所以完了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值