定位服务是手机上最常用的功能之一,据说也是相对比较简单的服务,所以从这里入手。其他系统服务的架构都是类似的。明白其中一个之后,再去理解其他的会容易得多。下面以 Android 源码为基础,大致分析了 Android 系统中定位服务的架构和实现。版本是6.0.1。

一. 应用层:
1.在App中调用位置服务

在Android App中使用定位服务,要先向系统请求一个LocationManager实例,
LocationManager mLocationManager = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);

然后用Criteria对其进行设置,获取一个provider,provider有3种基本定位类型 network/gps/passive
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
...
String provider = mLocationManager.getBestProvider(criteria, true);

(1)LocationManager利用provider直接获取一个最新的位置信息
Location location = mLocationManager.getLastKnownLocation(provider);

(2)使用事件绑定的方式,获取更新的位置信息
LocationListener{
 ...
 public void onLocationChanged(Location location)
}

二.框架层
2.LocationManager类的实现(
/frameworks/base/location/java/android/location/LocationManager.java)
其代码的主要作用是访问系统位置服务LocationManagerService
关键成员
private final ILocationManager mService;

构造器
public LocationManager(Context context, ILocationManager service);
ILocationManager与系统服务通信的接口

mService=Service;

如getProviders方法,实际是通过mService成员请求系统服务响应这个方法

public List<String> getProviders(boolean enabledOnly) {
 ...
 return mService.getProviders(null, enabledOnly);
}

3.接口定义(/frameworks/base/location/java/android/location/ILocationManager.aidl)
通过aidl定义通信接口,与系统位置服务进行进程间通信icp(涉及binder)

4.LocationManagerService的实现(/frameworks/base/services/core/java/com/android/server/LocationManagerService.java)
系统位置服务的实现,包括实现LocationManager调用的接口


public List<String> getProviders(Criteria criteria, boolean enabledOnly) 
public Location getLastLocation(LocationRequest request, String packageName)
...

在LocationManagerService中主要是有两种定位方式,一种通过网络,一种通过GPS模块。通过GPS模块定位的是GpsLocationProvider。

5.GpsLocationProvider(frameworks/base/services/core/java/com/android/server/location/GpsLocationProvider.java)

核心的涉及定位的方法是native的,通过JNI与HAL层C++语言函数交互

如这个注入一条位置信息的函数,接下来主要以他为线索。
private native void native_inject_location(double latitude, double longitude, float accuracy);

 三、硬件抽象层(HAL)
6.GpsLocationProvider 本地方法在HAL层的实现(
/frameworks/base/services/core/jni/com_android_server_location_GpsLocationProvider.cpp)
#include "hardware/hardware.h"
#include "hardware/gps.h"     //这里的hardware目录为/hardware/libhardware/include/hardware/
...

上面第5点中native_inject_location方法对应的实现

static void android_location_GpsLocationProvider_inject_location(JNIEnv* /* env */,
        jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy)
{
    if (sGpsInterface)
        sGpsInterface->inject_location(latitude, longitude, accuracy);
}
可以看出这里是通过sGpsInterface调用下一层函数去实现,他是一个GpsInterface结构体指针,
static const GpsInterface* sGpsInterface = NULL;

GpsInterface结构体定义在gps.h

结构体包含函数指针,则sGpsInterface引用的实例包含函数的具体实现
    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;

    //在这里获得了device提供的具体的sGpsInterface 
            sGpsInterface = gps_device->get_gps_interface(gps_device);
        }
    }

7.上面提到的gps.h(/hardware/libhardware/include/hardware/gps.h)

GpsInterface的定义

typedef struct {
    ...
    /** 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);

...
} GpsInterface;

四、高通的一个实现

硬件厂商主要的工作室引用gps.h, 实现一个gps.c,把GpsInterface等内容实现了。这里分析一下高通的一个实现。
8.gps.c(/hardware/qcom/gps/loc_api/libloc_api_50001/gps.c)
#include <hardware/gps.h>
...
extern const GpsInterface* get_gps_interface();  //外部函数

const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev)
{
    return get_gps_interface();          
    //在高通的实现中,第6点中的gps_device->get_gps_interface()调用的函数来自于此,此处
    //返回的函数指针是一个外部函数,该外部函数实际在9.2中实现
}
...

//dev结构体
struct gps_device_t *dev = (struct gps_device_t *) malloc(sizeof(struct gps_device_t));
...

//给dev结构体get_gps_interface的函数指针指向前面高通实现的函数。
dev->get_gps_interface = gps__get_gps_interface;

9.loc.cpp(/hardware/qcom/gps/loc_api/libloc_api_50001/loc.cpp)
9.1
//这里定义的静态函数,供同一个文件里的sLocEngInterface使用
static int  loc_init(GpsCallbacks* callbacks);
static int  loc_start();
static int  loc_inject_time(GpsUtcTime time, int64_t timeReference, int uncertainty);
static int  loc_inject_location(double latitude, double longitude, float accuracy);
...

//在gps.h中的GpsInterface,在这里被实现成了sLocEngInterface
static const GpsInterface sLocEngInterface =
{
   sizeof(GpsInterface),
   loc_init,
   loc_start,
   loc_inject_time,
   loc_inject_location,      
   ...
};

9.2
// for gps.c
extern "C" const GpsInterface* get_gps_interface(){
    ...
}

9.3

这个文件里的静态函数的具体实现
static int loc_inject_location(double latitude, double longitude, float accuracy)
{
    ENTRY_LOG();

int ret_val = 0;
    ret_val = loc_eng_inject_location(loc_afw_data, latitude, longitude, accuracy);

  //这里又是依靠调用其它函数,还要继续深挖到 loc_eng,在第10点

EXIT_LOG(%d, ret_val);
    return ret_val;
}

10.loc_eng.cpp(/hardware/qcom/gps/loc_api/libloc_api_50001/loc_eng.cpp)
int loc_eng_inject_location(loc_eng_data_s_type &loc_eng_data, double latitude,
                            double longitude, float accuracy)
{
    ENTRY_LOG_CALLFLOW();
    INIT_CHECK(loc_eng_data.adapter, return -1);
    LocEngAdapter* adapter = loc_eng_data.adapter;
    if(adapter->mSupportsPositionInjection)
    {
        adapter->sendMsg(new LocEngInjectLocation(adapter, latitude, longitude,
                                                  accuracy));

    //这里发出了消息
    }

EXIT_LOG(%d, 0);
    return 0;
}

再往下就得是Linux kernel里面GPS模块的写的驱动程序了,应该通过UART,传送基本的数据和控制命令,我就没去看了。。。

第一次看Android源码,简单分析,水平有限,如有错漏,还请包涵。

原文地址: http://www.cnblogs.com/aureate-sunshine/p/5520207.html

Android 6.0.1 Location Service 分析相关推荐

  1. Android 11.0 Settings源码分析 - 主界面加载

    Android 11.0 Settings源码分析 - 主界面加载 本篇主要记录AndroidR Settings源码主界面加载流程,方便后续工作调试其流程. Settings代码路径: packag ...

  2. Android 8.0系统源码分析--Camera processCaptureResult结果回传源码分析

    相机,从上到下概览一下,真是太大了,上面的APP->Framework->CameraServer->CameraHAL,HAL进程中Pipeline.接各种算法的Node.再往下的 ...

  3. android serviceconnection 码源分析,Android 7.0以上Accessibility Service DispatchGesture调用流程...

    概述 Accessibility Service被广泛用于各类自动点击的app,但早期,它并没有提供丰富的API,受到控件的高度约束,能达成的效果与Instrumentation相去甚远. Andro ...

  4. Android 5.0 Usb调试拦截分析及修改

    当我们调试安卓机器时,第一次插上usb线,会弹出一个授权的对话框,(前提是打开了usb调试功能)点击确认,才会允许调试. 如果我们想机器默认就可以调试该怎么做呢? 如果我们想动态拦截,需要用户输入帐号 ...

  5. android 9.0新ui,SystemUI分析(Android9.0)

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 一.SystemUI组成 SystemUI是Android的系统界面,包括状态栏statusbar.锁屏keyboard ...

  6. Android 7.0 分屏原理分析

    在以往的Android系统上,所有Activity都是全屏的,如果不设置透明效果,一次只能看到一个Activity界面. 但是从Android N(7.0)版本开始,系统支持了多窗口功能.在有了多窗口 ...

  7. Android 8.0系统源码分析--开篇

    个人分类: Android框架总结Android源码解析android framework 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/sinat ...

  8. Android 6.0 状态栏信号图标分析

    先来一张状态栏的分区图.今天要分析的是信号显示这一小块,就是图中的signal_cluster,对应源码中的View就是SignalClusterView. 这是一个自定义View,我们看一下他的定义 ...

  9. android 6.0 SystemUI源码分析(1)-SystemUI介绍

    1. SystemUI介绍 SystemUI是一个系统应用,主要功能有: 1)状态栏信息显示,比如电池,wifi信号,3G/4G等icon显示 2)通知面板,比如系统消息,第三方应用消息,都是在通知面 ...

最新文章

  1. Python之pandas读取Excel表格空值为nan的处理
  2. 在域模式中控制客户端运行和禁止软件
  3. 【放置奇兵】天六水晶和心三水晶(宝石、心灵水晶)
  4. 微信小程序开发02-小程序基本介绍
  5. MySQL初级培训_Mysql初级学习
  6. PRD的编写竟然暗含这个思路
  7. oracle plsql递归查询语句,oracle with 语句实现递归查询
  8. iPhone 12将首次加入屏下指纹?都是为它铺路?
  9. 织梦ajax加载文章列表,织梦dedecms首页列表页ajax点击下拉加载更多文章瀑布流效果...
  10. 您如何计算Visual Studio解决方案中的代码行?
  11. win11右键菜单怎么修改 Windows11修改右键菜单为win10风格的步骤方法
  12. 使用apidoc 生成Restful web Api文档——新手问题与解决方法
  13. Visio 2003 开发入门
  14. idea简单破解方式
  15. hls视频demo搭建简易服务器模拟运行
  16. 【整理】system\app中的APK一览
  17. linux内核模块Makefile的解析
  18. ilight app android,iLight pro
  19. 什么是数据描述统计分析指标?
  20. html JS打印添加水印图片

热门文章

  1. 《博客园精华集》Sharepoint+MOSS分册
  2. Matlab画图小结(一)
  3. Win10:tensorflow 学习笔记(1)
  4. 【笔记】基于 Mask R-CNN 的玉米田间杂草检测方法
  5. 吴恩达《Machine Learning》精炼笔记 10:异常检测
  6. 台湾大学林轩田机器学习技法课程学习笔记5 -- Kernel Logistic Regression
  7. jsp可以使用iframe_使用 JavaScript object URLs,可以处理图像、音频和视频
  8. 关于iis部署的一些小问题
  9. Delphi与c++ 数据类型对照表(从万一的博客园摘录)
  10. javascript中清空数组的两种方式