android gps机制分析--之三

来源:互联网 发布:招商银行java面试 编辑:程序博客网 时间:2024/06/07 12:39

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方法。主要的流程图如下,


在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库

2,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方法,其他的回调对应的也一样。

原创粉丝点击