Android 6.0.1 Location Service 分析
定位服务是手机上最常用的功能之一,据说也是相对比较简单的服务,所以从这里入手。其他系统服务的架构都是类似的。明白其中一个之后,再去理解其他的会容易得多。下面以 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 分析相关推荐
- Android 11.0 Settings源码分析 - 主界面加载
Android 11.0 Settings源码分析 - 主界面加载 本篇主要记录AndroidR Settings源码主界面加载流程,方便后续工作调试其流程. Settings代码路径: packag ...
- Android 8.0系统源码分析--Camera processCaptureResult结果回传源码分析
相机,从上到下概览一下,真是太大了,上面的APP->Framework->CameraServer->CameraHAL,HAL进程中Pipeline.接各种算法的Node.再往下的 ...
- android serviceconnection 码源分析,Android 7.0以上Accessibility Service DispatchGesture调用流程...
概述 Accessibility Service被广泛用于各类自动点击的app,但早期,它并没有提供丰富的API,受到控件的高度约束,能达成的效果与Instrumentation相去甚远. Andro ...
- Android 5.0 Usb调试拦截分析及修改
当我们调试安卓机器时,第一次插上usb线,会弹出一个授权的对话框,(前提是打开了usb调试功能)点击确认,才会允许调试. 如果我们想机器默认就可以调试该怎么做呢? 如果我们想动态拦截,需要用户输入帐号 ...
- android 9.0新ui,SystemUI分析(Android9.0)
8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 一.SystemUI组成 SystemUI是Android的系统界面,包括状态栏statusbar.锁屏keyboard ...
- Android 7.0 分屏原理分析
在以往的Android系统上,所有Activity都是全屏的,如果不设置透明效果,一次只能看到一个Activity界面. 但是从Android N(7.0)版本开始,系统支持了多窗口功能.在有了多窗口 ...
- Android 8.0系统源码分析--开篇
个人分类: Android框架总结Android源码解析android framework 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/sinat ...
- Android 6.0 状态栏信号图标分析
先来一张状态栏的分区图.今天要分析的是信号显示这一小块,就是图中的signal_cluster,对应源码中的View就是SignalClusterView. 这是一个自定义View,我们看一下他的定义 ...
- android 6.0 SystemUI源码分析(1)-SystemUI介绍
1. SystemUI介绍 SystemUI是一个系统应用,主要功能有: 1)状态栏信息显示,比如电池,wifi信号,3G/4G等icon显示 2)通知面板,比如系统消息,第三方应用消息,都是在通知面 ...
最新文章
- Python之pandas读取Excel表格空值为nan的处理
- 在域模式中控制客户端运行和禁止软件
- 【放置奇兵】天六水晶和心三水晶(宝石、心灵水晶)
- 微信小程序开发02-小程序基本介绍
- MySQL初级培训_Mysql初级学习
- PRD的编写竟然暗含这个思路
- oracle plsql递归查询语句,oracle with 语句实现递归查询
- iPhone 12将首次加入屏下指纹?都是为它铺路?
- 织梦ajax加载文章列表,织梦dedecms首页列表页ajax点击下拉加载更多文章瀑布流效果...
- 您如何计算Visual Studio解决方案中的代码行?
- win11右键菜单怎么修改 Windows11修改右键菜单为win10风格的步骤方法
- 使用apidoc 生成Restful web Api文档——新手问题与解决方法
- Visio 2003 开发入门
- idea简单破解方式
- hls视频demo搭建简易服务器模拟运行
- 【整理】system\app中的APK一览
- linux内核模块Makefile的解析
- ilight app android,iLight pro
- 什么是数据描述统计分析指标?
- html JS打印添加水印图片
热门文章
- 《博客园精华集》Sharepoint+MOSS分册
- Matlab画图小结(一)
- Win10:tensorflow 学习笔记(1)
- 【笔记】基于 Mask R-CNN 的玉米田间杂草检测方法
- 吴恩达《Machine Learning》精炼笔记 10:异常检测
- 台湾大学林轩田机器学习技法课程学习笔记5 -- Kernel Logistic Regression
- jsp可以使用iframe_使用 JavaScript object URLs,可以处理图像、音频和视频
- 关于iis部署的一些小问题
- Delphi与c++ 数据类型对照表(从万一的博客园摘录)
- javascript中清空数组的两种方式