GPS机制分析(3)

news/2024/7/4 1:09:01

1. gps打开/初始化

​ 在Java层打开gps,其实对于gps库来说,就是执行初始化过程。

1.1 Java层分析

​ android系统中打开GPS的方法往数据库里面写值,

private void enableGps(boolean enable) {
try {
	Settings.Secure.setLocationProviderEnabled(getContentResolver(),
					LocationManager.GPS_PROVIDER, enable);
		} catch (Exception e) {
		}
	}

最后往setting数据库中的location_providers_allowed字段写值。

putStringForUser(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider, userId);

LocationManagerService的systemRunning方法中会监听setting数据库中的location_providers_allowed字段值的变化,

mContext.getContentResolver().registerContentObserver(
    Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
                new ContentObserver(mLocationHandler) {
                    @Override
                    public void onChange(boolean selfChange) {
                        synchronized (mLock) {
                            updateProvidersLocked();
                        }
                    }
                }, UserHandle.USER_ALL);

如果该值有变化,则调用updateProvidersLocked方法。主要的流程图如下,

img

在updateProvidersLocked方法中,如果支持gps,调用updateProviderListenersLocked方法,

updateProviderListenersLocked(name, true);

updateProviderListenersLocked主要方法如下,

•••••
boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
••••
if (enabled) {
            p.enable();
            if (listeners > 0) {
                applyRequirementsLocked(provider);
            }
        } else {
            p.disable();
        }

首先调用isAllowedByCurrentUserSettingsLocked方法读取数据库字段值,然后根据该值进行相应的打开/关闭GPS操作。

private boolean isAllowedByCurrentUserSettingsLocked(String provider) {
        if (mEnabledProviders.contains(provider)) {
            return true;
        }
        if (mDisabledProviders.contains(provider)) {
            return false;
        }
        // Use system settings
        ContentResolver resolver = mContext.getContentResolver();
 
        return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId);
    }

Settings中的isLocationProviderEnabledForUser方法如下,

public static final boolean isLocationProviderEnabledForUser(ContentResolver cr, String provider, int userId) {
            String allowedProviders = Settings.Secure.getStringForUser(cr,
                    LOCATION_PROVIDERS_ALLOWED, userId);
            return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
        }

GpsLocationProvider的enable方法如下,

@Override
    public void enable() {
        synchronized (mLock) {
            if (mEnabled) return;
            mEnabled = true;
        }
 
        sendMessage(ENABLE, 1, null);
    }

ProviderHandler对ENABLE消息处理如下,

case ENABLE:
      if (msg.arg1 == 1) {
          handleEnable();
       } else {
          handleDisable();
      }
     break;

handleEnable方法如下,

private void handleEnable() {
        if (DEBUG) Log.d(TAG, "handleEnable");
        boolean enabled = native_init(); //初始化GPS HAL层模块
        if (enabled) {
            mSupportsXtra = native_supports_xtra();//判断GPS模块是否支持Xtra
            // TODO: remove the following native calls if we can make sure they are redundant.
            if (mSuplServerHost != null) {// 设置SUPL服务器地址和端口
                native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
            }
            if (mC2KServerHost != null) { //设置CDMA2000
                native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
            }
            mGpsMeasurementsProvider.onGpsEnabledChanged();
            mGpsNavigationMessageProvider.onGpsEnabledChanged();
        } else {
            synchronized (mLock) {
                mEnabled = false;
            }
            Log.w(TAG, "Failed to enable location provider");
        }
    }

1.2 HAL初始化

com_android_server_location_GpsLocationProvider的android_location_GpsLocationProvider_init方法如下,

static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj)
{
    // this must be set before calling into the HAL library
    if (!mCallbacksObj)
        mCallbacksObj = env->NewGlobalRef(obj);
 
    // fail if the main interface fails to initialize
    if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
        return JNI_FALSE;
 
    // if XTRA initialization fails we will disable it by sGpsXtraInterface to NULL,
    // but continue to allow the rest of the GPS interface to work.
    if (sGpsXtraInterface && sGpsXtraInterface->init(&sGpsXtraCallbacks) != 0)
        sGpsXtraInterface = NULL;
    if (sAGpsInterface)
        sAGpsInterface->init(&sAGpsCallbacks);
    if (sGpsNiInterface)
        sGpsNiInterface->init(&sGpsNiCallbacks);
    if (sAGpsRilInterface)
        sAGpsRilInterface->init(&sAGpsRilCallbacks);
    if (sGpsGeofencingInterface)
        sGpsGeofencingInterface->init(&sGpsGeofenceCallbacks);
 
    return JNI_TRUE;
}

主要是向HAL层设置回调方法接口,当HAL层有情况需要通知JNI层时,就会回调这些方法。

这6组回调方法的定义,回调方法几乎完全一样。sGpsCallbacks的定义如下,

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,
    request_utc_time_callback,
};

sGpsCallbacks中包含9个回调方法。

这样,HAL库就可以回调C方法了。

由此可见, com_android_server_location_GpsLocationProvider只是Java和HAL库之间的一个纽带。

  1. Java中加载HAL库,并且对HAL库进行初始化。然后就可以对HAL的GPS发出指令,例如打开,关闭GPS等。这时数据流的方向为,

Java–>JNI–> GPS库

  1. GPS库中执行打开/关闭动作,向Java上报卫星以及定位消息。这时数据流的方向为,

GPS库–>JNI–> Java

GPS库中对应的init方法为, loc.cpp 的loc_init方法,

static int loc_init(GpsCallbacks* callbacks)
{
    int retVal = -1;
    ENTRY_LOG();
    LOC_API_ADAPTER_EVENT_MASK_T event;
    if (NULL == callbacks) {
        LOC_LOGE("loc_init failed. cb = NULL\n");
        EXIT_LOG(%d, retVal);
        return retVal;
    }
 
    event = LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT |
            LOC_API_ADAPTER_BIT_SATELLITE_REPORT |
            LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST |
            LOC_API_ADAPTER_BIT_ASSISTANCE_DATA_REQUEST |
            LOC_API_ADAPTER_BIT_IOCTL_REPORT |
            LOC_API_ADAPTER_BIT_STATUS_REPORT |
            LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT |
            LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST;
            // 继续注册回调
    LocCallbacks clientCallbacks = {local_loc_cb, /* location_cb */
                                    callbacks->status_cb, /* status_cb */
                                    local_sv_cb, /* sv_status_cb */
                                    callbacks->nmea_cb, /* nmea_cb */
                                    callbacks->set_capabilities_cb, /* set_capabilities_cb */
                                    callbacks->acquire_wakelock_cb, /* acquire_wakelock_cb */
                                    callbacks->release_wakelock_cb, /* release_wakelock_cb */
                                    callbacks->create_thread_cb, /* create_thread_cb */
                                    NULL, /* location_ext_parser */
                                    NULL, /* sv_ext_parser */
                                    callbacks->request_utc_time_cb, /* request_utc_time_cb */
                                    };
 
    gps_loc_cb = callbacks->location_cb;
    gps_sv_cb = callbacks->sv_status_cb;
          // loc_eng_init以及里面的方法较复杂,暂不论述。
    retVal = loc_eng_init(loc_afw_data, &clientCallbacks, event, NULL);
    loc_afw_data.adapter->mSupportsAgpsRequests = !loc_afw_data.adapter->hasAgpsExtendedCapabilities();
    loc_afw_data.adapter->mSupportsPositionInjection = !loc_afw_data.adapter->hasCPIExtendedCapabilities();
    loc_afw_data.adapter->mSupportsTimeInjection = !loc_afw_data.adapter->hasCPIExtendedCapabilities();
    loc_afw_data.adapter->setGpsLockMsg(0);
    loc_afw_data.adapter->requestUlp(getCarrierCapabilities());
    loc_afw_data.adapter->setXtraUserAgent();
 
    if(retVal) {
        LOC_LOGE("loc_eng_init() fail!");
        goto err;
    }
 
    loc_afw_data.adapter->setPowerVoteRight(loc_get_target() == TARGET_QCA1530);
    loc_afw_data.adapter->setPowerVote(true);
 
    LOC_LOGD("loc_eng_init() success!");
 
err:
    EXIT_LOG(%d, retVal);
    return retVal;
}

gps.h中有对应的GpsCallbacks结构,

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;
    gps_request_utc_time request_utc_time_cb;
} GpsCallbacks;

这样,HAL层的gps_location_callback方法就对应com_android_server_location_GpsLocationProvide

中的location_callback方法,其他的回调对应的也一样。


http://www.niftyadmin.cn/n/2828934.html

相关文章

转WCF中出现死锁或者超时

WCF回调中的死锁 一、服务器端死锁 对于如下服务: [ServiceContract(CallbackContract typeof(INotify))]public class DownloadService{[OperationContract]public void Download(){//开始下载操作//.....//通知下载完成var callback OperationContext.Current.G…

ConcurrentMultiMap 实现

2019独角兽企业重金招聘Python工程师标准>>> Index&#xff0c;akka用来存储对应dispatcher和actor的&#xff0c;也是Akka实现的ConcurrentMultiMap<K,V> key类型自定义&#xff0c;value是由ConcurrentSkipListSet构成的,内部其实就对ConcurrentMultiMap<…

GPS机制分析(5)

1. 概述 ​ 上面的几篇文章论述了gps的打开启动初始化等动作,万事俱备只欠东风了。这一系列文章主要讲的是Position信息如何从modem层传递到loc eng层最后一直到Java上层的。由于loc eng层到modem层是属于消息触发的&#xff0c;也就是说正常的流程是&#xff1a;modem层传上来…

GPS机制分析(6)

7. gps数据从HAL传输到Java ​ 上面UlpLocation类型的mLocation作为参数传入&#xff0c;这里传递的还是UlpLocation类型的数据&#xff0c;不是hal层使用的GpsLocation类型&#xff0c;因此我们看一下UlpLocation类型的数据转换成GpsLocation类型的数据的过程&#xff1a; h…

IPC—Android Binder (1)

IPC是Inter-Process Communication的缩写&#xff0c;含义就是跨进程通信。 多进程场景 WebView加载图片推送 原因 内存不够->内存就够了 App运行独立的虚拟机——每个进程分配运行内存是有限的——32M、64M、48M 加载一个大图片——直接OOM 如果一旦奔溃&#xff0c;…

AndroidGPS定位应用流程

AndroidGPS定位应用流程 这里先了解下应用层流程。 根据这个框架&#xff0c;GPS在应用层实现的最基本流程示例&#xff1a; public class MainActivity extends Activity {private LocationManager mLocationManager;Overrideprotected void onDestroy() {super.onDestroy…

怎么把照片做成消消乐_开心消消乐特效制作如何快速的消除过关

开心消消乐特效制作如何快速的消除过关。在闯关的时候&#xff0c;我们想要制作三星过关&#xff0c;特效的制作是我们必须的过程。如果没有特效帮助我们大量的消除&#xff0c;想要得到3星的分数是比较困难的。但是在释放特效的时候&#xff0c;我们是需要一定的技巧的。单独的…

debian卸载php_在 Ubuntu/Debian 下安装 PHP7.3 教程

介绍最近的 PHP 7.3.0 已经在 2018 年12月6日 发布 GA&#xff0c;大家已经可以开始第一时间体验新版本了&#xff0c;这里先放出 PHP7.3 安装的教程以便大家升级。适用系统&#xff1a; Ubuntu 18.04 LTS / Ubuntu 16.04 LTS &#xff0f; Ubuntu 14.04 LTS / Debian 9 stretc…