通过修改android系统源码下载,可以实现伪造GPS数据吗

再吸金!SE推出《最终幻想:全员勇者》钥匙扣
再吸金!SE推出《最终幻想:全员勇者》钥匙扣
再吸金!SE推出《最终幻想:全员勇者》钥匙扣
再吸金!SE推出《最终幻想:全员勇者》钥匙扣
再吸金!SE推出《最终幻想:全员勇者》钥匙扣
再吸金!SE推出《最终幻想:全员勇者》钥匙扣
再吸金!SE推出《最终幻想:全员勇者》钥匙扣
再吸金!SE推出《最终幻想:全员勇者》钥匙扣
威锋网7月10日消锋网7月10日消息,《植物大战僵尸2》 如今...
威锋网7月10日消息,《植物大...
近日,开发商 Esquilax Games ..
说到方块游戏,相信有很多朋友应该还会记得 Gavina Games 早...
威锋网7月10日消息,《植物大...
近日,开发商 Esquilax Games ..
说到方块游戏,相信有很多朋友应该还会记得 Gavina Games 早...
再吸金!SE推出《最终幻想:全员勇者》钥匙扣
再吸金!SE推出《最终幻想:全员勇者》钥匙扣
再吸金!SE推出《最终幻想:全员勇者》钥匙扣
再吸金!SE推出《最终幻想:全员勇者》钥匙扣
再吸金!SE推出《最终幻想:全员勇者》钥匙扣
再吸金!SE推出《最终幻想:全员勇者》钥匙扣
再吸金!SE推出《最终幻想:全员勇者》钥匙扣
再吸金!SE推出《最终幻想:全员勇者》钥匙扣
您需要通过验证再能继续浏览 3秒后开始验证
威锋旗下产品
Hi~我是威威!
 粤公网安备 11号
新三板上市公司威锋科技(836555)
增值电信业务经营许可证:
Powered by Discuz!Google Play 改变关于 location.gps feature 的设定
核心提示:21号收到一封 Google Play 发来的邮件,告知如下信息: Hello Google Play Developer,We're writing to let you know that the apps listed at the end of this email may be affected by an upcoming platform change.Action required: If your app requires
21号收到一封 Google Play 发来的邮件,告知如下信息:
Hello Google Play Developer,We're writing to let you know that the apps listed at the end of this email may be affected by an upcoming platform change.Action required: If your app requires GPS hardware to operate properly, you will need to explicitly add the &android.hardware.location.gps& uses-feature to your manifest....
大概意思是,对于 target sdk &= 21(5.0) 的 APK 包,使用 ACCESS_FINE_LOCATION 权限的时候,并不会隐含的申请 android.hardware.location.gps 这个权限。
可能带来的后果是,一些没有 GPG 芯片的设备,也可以安装这个 APK,导致用户体验就很不好。
需要做的是,显式的声明对这个权限的使用。
翻了下关于这个权限的文档:
StackOverflow 讨论
uses-feature 这个机制,主要是方便 APP 商店过滤和匹配设备与 APK。
官方希望大家显式的声明需要用到的硬件或者软件 feature,但是做了隐含的声明机制。
例如在使用 ACCESS_WIFI_STATE 这个权限的时候,会隐含的加入 android.hardware.wifi ,这一点,可以使用如下命令来确认:
apt dump bading &apk-path&
在 target sdk &= 21(5.0) 有了些改变, ACCESS_COARSE_LOCATION 不再隐含加入 android.hardware.location.network , ACCESS_FINE_LOCATION 不再隐含加入 android.hardware.location.gps 。
对于使用 apt dum badging 命令得出结果,有一点其实有疑问:
编译条件:
compileSdkVersion 23buildToolsVersion '23.0.2'minSdkVersion 14targetSdkVersion 23
~/sdk/build-tools/23.0.1/aapt dum badging dev-com-debug.apk
uses-feature: name='android.hardware.location'uses-implied-feature: name='android.hardware.location' reason='requested android.permission.ACCESS_COARSE_LOCATION permission, and requested android.permission.ACCESS_FINE_LOCATION permission'uses-feature: name='android.hardware.location.gps'uses-implied-feature: name='android.hardware.location.gps' reason='requested android.permission.ACCESS_FINE_LOCATION permission'uses-feature: name='android.hardware.location.network'uses-implied-feature: name='android.hardware.location.network' reason='requested android.permission.ACCESS_COARSE_LOCATION permission'uses-feature: name='android.hardware.touchscreen'uses-implied-feature: name='android.hardware.touchscreen' reason='default feature for all apps'uses-feature: name='android.hardware.wifi'uses-implied-feature: name='android.hardware.wifi' reason='requested android.permission.ACCESS_WIFI_STATE permission'
为什么这里面还是隐含使用了 android.hardware.location.gps 等 feature?可能 AAPT 的 print 规则和最新的现在规则不一致?
要做的改变
这个机制只会影响 target sdk &= 21(5.0) 的 APK
最好显式的加入 uses-feature ,否则 Google Play 会认为你不使用某些 feature,那就允许不具备某些 feature 的硬件安装这个 APK,可能会囧
在声明 uses-feature 的时候,注意 required ,在不显式设置的情况下,是 true。true 代表只有这个 feature 才能安装,false 代表没有也 OK
Bugtags 新增了下面两个 uses-feature
&uses-feature
android:name=&android.hardware.location.gps&
android:required=&false& /&&uses-feature
android:name=&android.hardware.location.network&
android:required=&false& /&
想要及时收到最新博客文章,请关注:
『mobdev』微信公众号二维码
小编为您推荐“Google Play 改变关于 location.gps feature 的设定”相关文章
这篇文章主要介绍了Android Wear计时器开发,需要的朋友可以参考下
长按gallery中的图片进行删除该图片的操作,具体实现如下,感兴趣的朋友可以参考下哈
本文将详细介绍android怎样自定义Intent选择界面的标题,提供相关参考方法
目前手机市场上android已经具有强大的霸主地位,吸引了很多的追棒者,android学习越来越火热,本文给大家介绍android学习笔记(二)之电话拨号器,感兴趣的朋友一起学习吧
这篇文章主要介绍了Android中检查、监听电量和充电状态的方法,如判断当前充电状态、监听充电状态的改变、判断当前剩余电量等,需要的朋友可以参考下
通知[Notification]是Android中比较有特色的功能,当某个应用程序希望给用户发出一些提示信息,而该应用程序又不在前台运行时,就可以借助通知实现。使用通知的步骤1、需要一个NotificationManager来获得NotificationManager manager = (NotificationManager
第一天上班,列了一下今年要学习的东西。主要就是深入学习Android相关的系统源代码,夯实基础。对于学习Android系统源代码,也没什么大概,就从我们平常使用最基础的东西学起,也就是从view这个切入点开始学习Android的源码,在没分析源码之前,我们有的时候
小编导读:获取视频的缩略图,截图正在播放的视频某一帧,是在音视频开发中,常遇到的问题。本文是主要用于点播中截图视频,同时还可以获取点播视频的缩略图进行显示,留下一个问题,如下图所示, 如果要获取直播中节目视频缩略图,该怎么做呢?(ps:直播是直
前言新的一年,大家新年快乐~~鸡年大吉!本次给大家带来何老师的最新文章~虽然何老师还在过节,但依然放心不下广大开发者,在此佳节还未结束之际,给大家带来最新的技术分享~ 事件的起因不说了,总之是需要实现一个 NDK 层的网络请求。为了多端适用,还是选择
引言Android应用程序的编译中,负责资源打包的是aapt,如果不对打包后的资源ID进行控制,就会导致插件中的资源ID冲突。所以,我们需要改写aapt的源码,以达到通过某种方式传递资源ID的Package ID,通过aapt打包时获取到这个Package ID并且应用才插件资源的命名
为什么要重视程序的架构设计 对程序进行架构设计的原因,归根结底是为了 提高生产力 。通过设计是程序模块化,做到模块内部的 高聚合 和模块之间的 低耦合 (如依赖注入就是低耦合的集中体现)。 这样做的好处是使得程序开发过程中,开发人员主需要专注于一点,
安卓逆向系列教程 4.2 分析锁机软件 作者: 飞龙 这个教程中我们要分析一个锁机软件。像这种软件都比较简单,完全可以顺着入口看下去,但我这里还是用关键点来定位。首先这个软件的截图是这样,进入这个界面之后,除非退出模拟器,否则没办法回到桌面。上面那
在前一篇博客 Android插件化(一):OpenAtlas架构以及实现原理概要 中,我们对应Android插件化存在的问题,实现原理,以及目前的实现方案进行了简单的叙述。从这篇开始,我们要深入到OpenAtlas的源码中进行插件安装过程的分析。 插件的安装分为3种:宿主启动时立
众所周知,Android开发者有中文网站了,API 指南一眼看去最左侧的菜单都是中文,然而点进去内容还是很多是英文,并没有全部翻译,我这里整理了API 指南的目录,便于查看,如果之前还没有通读,现在可以好好看一遍。注意,如果标题带有英文,说明官方还没有翻
问题以下是一段简单的代码,它调用系统的相机app来拍摄照片:void takePhoto(String cameraPhotoPath) {File cameraPhoto = new File(cameraPhotoPath);Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);takePhotoIntent.putExtra(MediAndroid系统Gps开发
Position& System 全球定位系统)和定位部分
除此之外还有利用基站(cell)定位的AGPS等设备
&定们系列统的基本架构
&主要数据来源有两个:
GPS定位和network定位(基于cell和wifi热点的定位)
定位部分的结构如图
& 定位系统的驱动层
&Network定位的底层驱动和适配层实际上就是RIL和wifi框架的组成部分
&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 {
size_t&&&&&&&&&
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
//设置位置模式
(*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence
recurrence,
&&&&&&&&&&&
uint32_t min_interval, uint32_t preferred_accuracy, uint32_t
preferred_time);
//获得扩展消息的指针
void* (*get_extension)(const char* name);
//表示GPS的定位信息
typedef struct {
size_t&&&&&&&&&
uint16_t&&&&&&&
//表示纬度
double&&&&&&&&&
//表示经度
double&&&&&&&&&
//以WGS84坐标系统表示的高度信息
double&&&&&&&&&
//速度& m/s
float&&&&&&&&&&
//表示方向
float&&&&&&&&&&
//表示精度
float&&&&&&&&&&
//表示时间戮
GpsUtcTime&&&&&
当上层调用: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*
& typedef struct {
size_t&&&&&
gps_location_callback location_
gps_status_callback status_
gps_sv_status_callback sv_status_
gps_nmea_callback nmea_
gps_set_capabilities set_capabilities_
gps_acquire_wakelock acquire_wakelock_
gps_release_wakelock release_wakelock_
gps_create_thread create_thread_
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
实现自已的gpscallbacks供GPS适配层调用
部分代码如下:
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
ILocationManager是android 定们系统的核心
LocationServiceManager是定位系统的服务器端,它在目录:\frameworks\base\services\java\com\android\server下
LocationProviderProxy mNetworkLocationProvider;
LocationProviderInterface mGpsLocationP
**************************************************************
2.3中的变化
**************************************************************
\frameworks\base\services\java\com\android\server\location目录下的GpsLocationProvider.java它直接继承
LocationProviderInterface(在2。3之前可能是LocationProviderImpl),
它提供了底层的控制接口,同时开启一个gpsEventThread通过轮询native_wait_for_event来取得底层上报的数据
App发出定位申请,启动定位服务线程,此线程会在APP framwork中调用location provider
通过被native方法调用到JNI中, JNI获得gpsInterface并传给接口一个回调函数的实现
gpsInterface就是HAL层最主要的实现
上层实现的思路
1、获取GPS的Location Provider。
&2、将此Provider传入到requestLocationUpdates()方法,让Android系统获知搜索位置方式。
&3、创建实现了GpsStatus.Listener接口的对象,重写onGpsStatusChanged()方法,向LocationManager添加次监听器,检测卫星状态。(可选步骤)
Android GPS 架构分析
Framework 层:
&代码路径为:
1 \frameworks\base\location\java\android\location
&供api调用
frameworks\base\location\java\com\android\internal\location
&这个目录是framework对location服务的内部实现
3 \frameworks\base\services\java\com\android\server
& 这是location服务对内部实现的一个封装
&代码路径:
在2。2版本中
frameworks/base/core/jni/android_location_GpsLocationProvider.cpp
在2.3版式本中
\frameworks\base\services\jni\com_android_server_location_GpsLocationProvider.cpp
上层承接freanwork,下层调用HAL
HAL硬件抽象层:
&\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&&&&&&&&&
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
(*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);
gpscallbacks回调函数结构体,定义同上,实现在com_android_server_android_location_GpsLocationProvider.cpp中
typedef struct {
size_t&&&&&
gps_location_callback location_
gps_status_callback status_
gps_sv_status_callback sv_status_
gps_nmea_callback nmea_
//以下几个回调函数是在2.3以后添加的回调函数
gps_set_capabilities set_capabilities_
gps_acquire_wakelock acquire_wakelock_
gps_release_wakelock release_wakelock_
gps_create_thread create_thread_
3 Gpslocation表示loaction数据信息 2.3比2.2多了个size属性
typedef struct {
//2.3之后添加
size_t&&&&&&&&&
uint16_t&&&&&&&
double&&&&&&&&&
double&&&&&&&&&
double&&&&&&&&&
float&&&&&&&&&&
float&&&&&&&&&&
float&&&&&&&&&&
GpsUtcTime&&&&&
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服务的代码段如下:
&&&&&&&&&&&&&&&
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 =
其中的locationF 是LocationManagerService的final类型,就是一旦赋值,不能更改。
if (locationF != null) locationF.systemReady();
LocationManagerService代码路径如下:\frameworks\base\services\java\com\android\server
构造器如下:
LocationManagerService(Context context) {
mContext =
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,
&&&&&&&&&&&&&&&
"(" + Settings.System.NAME + "=?)",
&&&&&&&&&&&&&&&
new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
&&&&&&&&&&&&&&&
mSettings = new ContentQueryMap(settingsCursor,
Settings.System.NAME, true, mLocationHandler);
SettingsObserver settingsObserver = new SettingsObserver();
mSettings.addObserver(settingsObserver);
初始化函数中,最重要的便是 loadProviders()函数。
private void loadProviders() {
synchronized (mLock) {
&&&&&&&&&&&
if (sProvidersLoaded) {
&&&&&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&&&&&&
// Load providers
&&&&&&&&&&&
loadProvidersLocked();
&&&&&&&&&&&
sProvidersLoaded =
&private void loadProvidersLocked() {
&&&&&&&&&&&
_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,
&&&&&&&&&&&
mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
&&&&&&&&&&&
mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
&&&&&&&&&&&
addProvider(gpsProvider);
&&&&&&&&&&&
mGpsLocationProvider = gpsP
// 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() {
hw_module_t*
GpsInterface* interface = NULL;
hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t
const**)&module);
&&& if (err
hw_device_t*
err = module-&methods-&open(module, GPS_HARDWARE_MODULE_ID,
if (err == 0) {
&&&&&&&&&&&
gps_device_t* gps_device = (gps_device_t *)
&&&&&&&&&&&
interface = gps_device-&get_gps_interface(gps_device);
&&& return
&get_gps_interface去打开模组,之后打开设备,然后通过设备区调用HAL层中的get_gps_interface(gps_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*
&&& 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 =
//mLocationManager就是第二个参数.也就是locationManagerService
mLocationManager = locationM
mNIHandler = new GpsNetInitiatedHandler(context);
mLocation.setExtras(mLocationExtras);
....................
_loadProvidersLocked函数,在构造完成后,将其add到全局变量ArrayList
mProviders中,备以后调用.
接着启动了两个线程,但是可惜的是这两个服务都无法启动,因为他们是通过配置文件conifg.xml
得到服务的名字,然后启动服务的。但是在这个配置文件中,两个服务的名字都是null
配置文件的路径为;framework/base/core/res/res/values
部分代码如下:
这就是为什么在调用getFromLocationName和 getFromLocation时会提示service not
available,2.2就存在的bug
在_loadProvidersLocked函数的最后调用的是updateProvidersLocked();也在这个类中
部分代码如下:
&private void updateProvidersLocked() {
boolean changesMade =
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 =
&&&&&&&&&&&
} else if (!isEnabled && shouldBeEnabled) {
&&&&&&&&&&&&&&&
updateProviderListenersLocked(name, true);
&&&&&&&&&&&&&&&
changesMade =
&&&&&&&&&&&
if (changesMade) {
&&&&&&&&&&&
mContext.sendBroadcast(new
Intent(LocationManager.PROVIDERS_CHANGED_ACTION));
在mProviders里面应该存在一个gpsProvider
和PassiveProvider,而gpsProvider是未被enable的。而passiveProvider是enable的。
这边我们对gpsProvider进行讨论,他执行的是updateProviderListenersLocked(name,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) {
&&&&&&&&&&&
ArrayList deadReceivers =
ArrayList records = mRecordsByProvider.get(provider);
if (records != null) {
&&&&&&&&&&&
final int N = records.size();
&&&&&&&&&&&
for (int i=0; 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();
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
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);
&&&&&&&&&&&
&&&&&&&&&&&
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);
&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&&&&&&
mHandler.sendMessage(m);
在handlerMessage 中的处理. 调用handleEnable();
&public void handleMessage(Message msg) {
&&&&&&&&&&&
int message = msg.
&&&&&&&&&&&
switch (message) {
&&&&&&&&&&&&&&&
case ENABLE:
&&&&&&&&&&&&&&&&&&&
if (msg.arg1 == 1) {
&&&&&&&&&&&&&&&&&&&&&&&
handleEnable();
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
handleDisable();
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
handleEnable 主要作了两件事,
1 调用本地方法 native_init(),初始化gps
本地方法的具体实现是在com_android_server_location_GpsLocationProvider.cpp中,
部分内容为下:
&&&&&&&&&&
static jboolean android_location_GpsLocationProvider_init(JNIEnv*
env, jobject obj)
//取得接口,并初始化gps
GpsInterface* interface = GetGpsInterface(env, obj);
(!interface)
(!sGpsDebugInterface)
sGpsDebugInterface = (const&&
GpsDebugInterface*)interface-&get_extension(GPS_DEBUG_INTERFACE);
&&& return
2 试图启动AGPS服务
&& 代码如下:
&private void handleEnable() {
if (DEBUG) Log.d(TAG, "handleEnable");
if (mEnabled)
//调用本地方法初始化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);
&&&&&&&&&&&
&&&&&&&&&&&
Log.w(TAG, "Failed to enable location provider");
取得接口的方法中,也调用了 get_gps_interface
代码如下:
static const GpsInterface* GetGpsInterface(JNIEnv* env, jobject
&&& // this
must be set before calling into the HAL library
(!mCallbacksObj)
mCallbacksObj = env-&NewGlobalRef(obj);
(!sGpsInterface) {
sGpsInterface = get_gps_interface();
if (!sGpsInterface || sGpsInterface-&init(&sGpsCallbacks) !=
&&&&&&&&&&&
sGpsInterface = NULL;
&&&&&&&&&&&
return NULL;
&&& return
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_
(!s-&init)
gps_state_init(s);
&&& if (s-&fd
return -1;
s-&callbacks = *
&&& return
在这个主方法中首先打开串口,然后进立socket通信,然后建立线程监听底层数据上报
static void
gps_state_init( GpsState*& state )
state-&init&&&&&&
state-&control[0] = -1;
state-&control[1] = -1;
state-&fd&&&&&&&&
&&& state-&fd
= qemud_channel_open(QEMU_CHANNEL_NAME);
(state-&fd & 0) {
D("no gps emulation detected");
&&& D("gps
emulation will read from '%s' qemud channel", QEMU_CHANNEL_NAME
socketpair( AF_LOCAL, SOCK_STREAM, 0, state-&control ) & 0 )
LOGE("could not create thread control socket pair: %s",
strerror(errno));
pthread_create( &state-&thread, NULL, gps_state_thread,
state ) != 0 ) {
LOGE("could not create gps thread: %s", strerror(errno));
&&& D("gps state
initialized");
gps_state_done( state );
该方法说明在初始化时调用的相关扩展接口是没用的
static const void*
qemu_gps_get_extension(const char* name)
extensions supported
&&& return
在2。2的时候handlerEnable还创建了一个监听线程
而在2.3中GpsLocationProvider(路径为:frameworks\base\services\java\com\android\server\location)
在构造函数中就创建了这个 监听线程
构造器中的部分代码
&mThread = new GpsLocationProviderThread();
mThread.start();
while (true) {
&&&&&&&&&&&
&&&&&&&&&&&&&&&
mInitializedLatch.await();
&&&&&&&&&&&&&&&
&&&&&&&&&&&
} 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
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) {
&&&&&&&&&&&
ArrayList deadReceivers =
ArrayList records = mRecordsByProvider.get(provider);
if (records != null) {
&&&&&&&&&&&
final int N = records.size();
&&&&&&&&&&&
for (int i=0; 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();
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
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);
&&&&&&&&&&&
&&&&&&&&&&&
p.enableLocationTracking(false);
&&&&&&&&&&&
p.disable();
enableLocationTracking在gpsLocationProvider.java中
& public void enableLocationTracking(boolean
// 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);
&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&&&&&&
mHandler.sendMessage(m);
& private final class ProviderHandler extends
public void handleMessage(Message msg) {
&&&&&&&&&&&
int message = msg.
&&&&&&&&&&&
switch (message) {
&&&&&&&&&&&&&&&
case ENABLE:
&&&&&&&&&&&&&&&&&&&
if (msg.arg1 == 1) {
&&&&&&&&&&&&&&&&&&&&&&&
handleEnable();
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
handleDisable();
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
case ENABLE_TRACKING:
&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&
handleEnableLocationTracking(msg.arg1 == 1);
&&&&&&&&&&&&&&&&&&&
handleEnableLocationTracking 函数
&private void
handleEnableLocationTracking(boolean enable) {
if (enable) {
&&&&&&&&&&&
mTTFF = 0;
&&&&&&&&&&&
mLastFixTime = 0;
&&&&&&&&&&&
startNavigating(false);
&&&&&&&&&&&
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 =
&&&&&&&&&&&
mSingleShot = singleS
&&&&&&&&&&&
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 =
&&&&&&&&&&&&&&&
Log.e(TAG, "set_position_mode failed in startNavigating()");
&&&&&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&&&&&&
//本地方法
&&&&&&&&&&&
if (!native_start()) {
&&&&&&&&&&&&&&&
mStarted =
&&&&&&&&&&&&&&&
Log.e(TAG, "native_start failed in startNavigating()");
&&&&&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&&&&&&
// 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)
GpsInterface* interface = GetGpsInterface(env, obj);
(interface)
//这里调用了接口的set_position_mode方法
return (interface-&set_position_mode(mode, recurrence,
min_interval, preferred_accuracy,
&&&&&&&&&&&&&&&
preferred_time) == 0);
&该方法调用了接口的set_position_mode方法,这个方法的实现在(模拟器)的相关类中可以看到期实现
部分代码如下;
static int qemu_gps_set_position_mode(GpsPositionMode mode, int
fix_frequency)
&&& // FIXME
- support fix_frequency
&&& return
2& native_start
通过向底层发送命令来启动GPS,&
这个底层就是enable/init函数中启动的等待数据的线程
static int
qemu_gps_start()
GpsState*& s = _gps_
(!s-&init) {
D("%s: called with uninitialized state !!", __FUNCTION__);
return -1;
&&& D("%s:
called", __FUNCTION__);
gps_state_start(s);
&&& return
static void& gps_state_start(
GpsState*& s )
char& cmd = CMD_START;
ret=write( s-&control[0], &cmd, 1 ); }
(ret & 0 && errno == EINTR);
&&& if (ret !=
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*)
NmeaReader& reader[1];
int&&&&&&&&
epoll_fd&& = epoll_create(2);
int&&&&&&&&
started&&& =
int&&&&&&&&
gps_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
&&& for (;;)
struct epoll_event&&
events[2];
int&&&&&&&&&&&&&&&&&
nevents = epoll_wait( epoll_fd, events, 2, -1 );
if (nevents & 0) {
&&&&&&&&&&&
if (errno != EINTR)
&&&&&&&&&&&&&&&
LOGE("epoll_wait() unexpected error: %s", strerror(errno));
&&&&&&&&&&&
D("gps thread received %d events", nevents);
for (ne = 0; ne & ne++) {
&&&&&&&&&&&
if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0) {
&&&&&&&&&&&&&&&
LOGE("EPOLLERR or EPOLLHUP after epoll_wait() !?");
&&&&&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&&&&&&
if ((events[ne].events & EPOLLIN) != 0) {
&&&&&&&&&&&&&&&
int& fd = events[ne].data.
&&&&&&&&&&&&&&&
if (fd == control_fd)
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
char& cmd = 255;
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
D("gps control fd event");
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
ret = read( fd, &cmd, 1 );
&&&&&&&&&&&&&&&&&&&
} while (ret & 0 && errno == EINTR);
&&&&&&&&&&&&&&&&&&&
if (cmd == CMD_QUIT) {
&&&&&&&&&&&&&&&&&&&&&&&
D("gps thread quitting on demand");
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
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 (;;) {
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
ret = read( fd, buff, sizeof(buff) );
&&&&&&&&&&&&&&&&&&&&&&&
if (ret & 0) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&
if (errno == EINTR)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&
if (errno != EWOULDBLOCK)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
LOGE("error while reading from gps daemon socket: %s:",
strerror(errno));
&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
D("received %d bytes: %.*s", ret, ret, buff);
&&&&&&&&&&&&&&&&&&&&&&&
for (nn = 0; nn & nn++)
&&&&&&&&&&&&&&&&&&&&&&&&&&&
nmea_reader_addc( reader, buff[nn] );
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
D("gps fd event end");
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
LOGE("epoll_wait() returned unkown fd %d ?", fd);
&&&&&&&&&&&&&&&
&&&&&&&&&&&
&&& return
&这个监听线程最主要的一个就是nmea_reader_set_callback(
其实就是注册了一个回调函数,location_cb 这个回调函数就是对底层location数据上报的回调函数。
enableLocationTracking函数完成了,
也就是LocationManageService.java中
updateProviderListenersLocked的完成
也就是updateProvidersLocked的完成,
也就是loadProviders函数的完成
也就是 initialize的完成,
也就是run的完成,
也就是systemReady的完成
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。}

我要回帖

更多关于 android聊天源码 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信