Android GPS学习 (一) :GPS 启动流程

一、Settings

打开GPS的方法往数据库里面写值,然后framework层读取值再做相应处理。

packages/apps/Settings/src/com/android/settings/location/LocationSwitchBarController.java

public void onSwitchChanged(Switch switchView, boolean isChecked) {
    mLocationEnabler.setLocationEnabled(isChecked);
}
void setLocationMode(int mode) {
    final int currentMode = Settings.Secure.getInt(mContext.getContentResolver(),
            Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
    if (isRestricted()) {
        // Location toggling disabled by user restriction. Read the current location mode to
        // update the location master switch.
        if (Log.isLoggable(TAG, Log.INFO)) {
            Log.i(TAG, "Restricted user, not setting location mode");
        }
        if (mListener != null) {
            mListener.onLocationModeChanged(currentMode, true);
        }
        return;
    }

    updateLocationMode(mContext, currentMode, mode, ActivityManager.getCurrentUser(),
            Settings.Secure.LOCATION_CHANGER_SYSTEM_SETTINGS);
    refreshLocationMode();
}

二、framework

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

/frameworks/base/services/core/java/com/android/server/LocationManagerService.java

// listen for settings changes
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方法。

private void updateProvidersLocked() {
    boolean changesMade = false;
    for (int i = mProviders.size() - 1; i >= 0; i--) {
        LocationProviderInterface p = mProviders.get(i);
        boolean isEnabled = p.isEnabled();
        String name = p.getName();
        boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
        if (isEnabled && !shouldBeEnabled) {
            updateProviderListenersLocked(name, false);
            mLastLocation.clear();
            mLastLocationCoarseInterval.clear();
            changesMade = true;
        } else if (!isEnabled && shouldBeEnabled) {
            updateProviderListenersLocked(name, true);
            changesMade = true;
        }
    }
    if (changesMade) {
        mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
                UserHandle.ALL);
        mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
                UserHandle.ALL);
    }
}
  •  

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

private void updateProviderListenersLocked(String provider, boolean enabled) {
    int listeners = 0;

    LocationProviderInterface p = mProvidersByName.get(provider);
    if (p == null) return;

    ArrayList<Receiver> deadReceivers = null;

    ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
    if (records != null) {
        for (UpdateRecord record : records) {
            if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
                // 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) {
            applyRequirementsLocked(provider);
        }
    } else {
        p.disable();
    }
}
  •  

GnssLocationProvider的enable方法如下:

/frameworks/base/services/core/java/com/android/server/location/GnssLocationProvider.java

GnssLocationProvider的enable方法如下:

public void enable() {
    synchronized (mLock) {
        if (mEnabled) return;
        mEnabled = true;
    }

    sendMessage(ENABLE, 1, null);
}
  •  

handlenable就是ENABLE的消息处理函数:

private void handleEnable() {
    if (DEBUG) Log.d(TAG, "handleEnable");

    boolean enabled = native_init();

    if (enabled) {
        mSupportsXtra = native_supports_xtra();

        // TODO: remove the following native calls if we can make sure they are redundant.
        if (mSuplServerHost != null) {
            native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
        }
        if (mC2KServerHost != null) {
            native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
        }

        mGnssMeasurementsProvider.onGpsEnabledChanged();
        mGnssNavigationMessageProvider.onGpsEnabledChanged();
        mGnssBatchingProvider.enable();
    } else {
        synchronized (mLock) {
            mEnabled = false;
        }
        Log.w(TAG, "Failed to enable location provider");
    }
}
  •  

三、HAL

底层GNSS服务启动

IGnss* HIDL_FETCH_IGnss(const char* /* hal */) {
    hw_module_t* module;
    IGnss* iface = nullptr;
    int 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) {
            iface = new Gnss(reinterpret_cast<gps_device_t*>(device));
        } else {
            ALOGE("gnssDevice open %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
        }
    } else {
      ALOGE("gnss hw_get_module %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
    }
    return iface;
}

mGnssIface底层modem 厂商驱动 interface

Gnss::Gnss(gps_device_t* gnssDevice) :
        mDeathRecipient(new GnssHidlDeathRecipient(this)) {
    /* Error out if an instance of the interface already exists. */
    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
    sInterfaceExists = true;

    if (gnssDevice == nullptr) {
        ALOGE("%s: Invalid device_t handle", __func__);
        return;
    }

    mGnssIface = gnssDevice->get_gps_interface(gnssDevice);
}

 Gnss::setCallback   gnssHal->setCallback(gnssCbIface);
 

// Methods from ::android::hardware::gnss::V1_0::IGnss follow.
Return<bool> Gnss::setCallback(const sp<IGnssCallback>& callback)  {
    if (mGnssIface == nullptr) {
        ALOGE("%s: Gnss interface is unavailable", __func__);
        return false;
    }

    if (callback == nullptr)  {
        ALOGE("%s: Null callback ignored", __func__);
        return false;
    }

    if (sGnssCbIface != NULL) {
        ALOGW("%s called more than once. Unexpected unless test.", __func__);
        sGnssCbIface->unlinkToDeath(mDeathRecipient);
    }

    sGnssCbIface = callback;
    callback->linkToDeath(mDeathRecipient, 0 /*cookie*/);

    // If this was received in the past, send it up again to refresh caller.
    // mGnssIface will override after init() is called below, if needed
    // (though it's unlikely the gps.h capabilities or system info will change.)
    if (sCapabilitiesCached != 0) {
        setCapabilitiesCb(sCapabilitiesCached);
    }
    if (sYearOfHwCached != 0) {
        LegacyGnssSystemInfo info;
        info.year_of_hw = sYearOfHwCached;
        setSystemInfoCb(&info);
    }

    return (mGnssIface->init(&sGnssCb) == 0);
}

native_init对应jni中的android_location_GpsLocationProvider_init函数,在该函数中调用了
sGpsInterface->init(&sGpsCallbacks),

frameworks/base/services/core/jni/com_android_server_location_GnssLocationProvider.cpp

{"native_init", "()Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_init)},
  •  
static jboolean android_location_GnssLocationProvider_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 (gnssHal == nullptr) {
        ALOGE("Unable to Initialize GNSS HAL\n");
        return JNI_FALSE;
    }

    sp<IGnssCallback> gnssCbIface = new GnssCallback();

    Return<bool> result = false;
    if (gnssHal_V1_1 != nullptr) {
        result = gnssHal_V1_1->setCallback_1_1(gnssCbIface);
    } else {
        result = gnssHal->setCallback(gnssCbIface);
    }
    if (!result.isOk() || !result) {
        ALOGE("SetCallback for Gnss Interface fails\n");
        return JNI_FALSE;
    }

    sp<IGnssXtraCallback> gnssXtraCbIface = new GnssXtraCallback();
    if (gnssXtraIface == nullptr) {
        ALOGE("Unable to initialize GNSS Xtra interface\n");
    } else {
        result = gnssXtraIface->setCallback(gnssXtraCbIface);
        if (!result.isOk() || !result) {
            gnssXtraIface = nullptr;
            ALOGI("SetCallback for Gnss Xtra Interface fails\n");
        }
    }

    sp<IAGnssCallback> aGnssCbIface = new AGnssCallback();
    if (agnssIface != nullptr) {
        agnssIface->setCallback(aGnssCbIface);
    } else {
        ALOGI("Unable to Initialize AGnss interface\n");
    }

    sp<IGnssGeofenceCallback> gnssGeofencingCbIface = new GnssGeofenceCallback();
    if (gnssGeofencingIface != nullptr) {
      gnssGeofencingIface->setCallback(gnssGeofencingCbIface);
    } else {
        ALOGI("Unable to initialize GNSS Geofencing interface\n");
    }

    sp<IGnssNiCallback> gnssNiCbIface = new GnssNiCallback();
    if (gnssNiIface != nullptr) {
        gnssNiIface->setCallback(gnssNiCbIface);
    } else {
        ALOGI("Unable to initialize GNSS NI interface\n");
    }

    sp<IAGnssRilCallback> aGnssRilCbIface = new AGnssRilCallback();
    if (agnssRilIface != nullptr) {
        agnssRilIface->setCallback(aGnssRilCbIface);
    } else {
        ALOGI("Unable to Initialize AGnss Ril interface\n");
    }

    return JNI_TRUE;
}

 

/packages/apps/Settings/src/com/android/settings/location/LocationEnabler.java

void setLocationMode(int mode) {
    final int currentMode = Settings.Secure.getInt(mContext.getContentResolver(),
            Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
    if (isRestricted()) {
        // Location toggling disabled by user restriction. Read the current location mode to
        // update the location master switch.
        if (Log.isLoggable(TAG, Log.INFO)) {
            Log.i(TAG, "Restricted user, not setting location mode");
        }
        if (mListener != null) {
            mListener.onLocationModeChanged(currentMode, true);
        }
        return;
    }

    updateLocationMode(mContext, currentMode, mode, ActivityManager.getCurrentUser(),
            Settings.Secure.LOCATION_CHANGER_SYSTEM_SETTINGS);
    refreshLocationMode();
}

 

 

二、framework

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

/frameworks/base/services/core/java/com/android/server/LocationManagerService.java

// listen for settings changes
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方法。

private void updateProvidersLocked() {
    boolean changesMade = false;
    for (int i = mProviders.size() - 1; i >= 0; i--) {
        LocationProviderInterface p = mProviders.get(i);
        boolean isEnabled = p.isEnabled();
        String name = p.getName();
        boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
        if (isEnabled && !shouldBeEnabled) {
            updateProviderListenersLocked(name, false);
            mLastLocation.clear();
            mLastLocationCoarseInterval.clear();
            changesMade = true;
        } else if (!isEnabled && shouldBeEnabled) {
            updateProviderListenersLocked(name, true);
            changesMade = true;
        }
    }
    if (changesMade) {
        mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
                UserHandle.ALL);
        mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
                UserHandle.ALL);
    }
}

 

 

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

private void updateProviderListenersLocked(String provider, boolean enabled) {
    int listeners = 0;

    LocationProviderInterface p = mProvidersByName.get(provider);
    if (p == null) return;

    ArrayList<Receiver> deadReceivers = null;

    ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
    if (records != null) {
        for (UpdateRecord record : records) {
            if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
                // 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) {
            applyRequirementsLocked(provider);
        }
    } else {
        p.disable();
    }
}

 

 

GnssLocationProvider的enable方法如下:

/frameworks/base/services/core/java/com/android/server/location/GnssLocationProvider.java

GnssLocationProvider的enable方法如下:

public void enable() {
    synchronized (mLock) {
        if (mEnabled) return;
        mEnabled = true;
    }

    sendMessage(ENABLE, 1, null);
}

 

 

handlenable就是ENABLE的消息处理函数:

private void handleEnable() {
    if (DEBUG) Log.d(TAG, "handleEnable");

    boolean enabled = native_init();

    if (enabled) {
        mSupportsXtra = native_supports_xtra();

        // TODO: remove the following native calls if we can make sure they are redundant.
        if (mSuplServerHost != null) {
            native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
        }
        if (mC2KServerHost != null) {
            native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
        }

        mGnssMeasurementsProvider.onGpsEnabledChanged();
        mGnssNavigationMessageProvider.onGpsEnabledChanged();
        mGnssBatchingProvider.enable();
    } else {
        synchronized (mLock) {
            mEnabled = false;
        }
        Log.w(TAG, "Failed to enable location provider");
    }
}

 

 

三、HAL

native_init对应jni中的android_location_GpsLocationProvider_init函数,在该函数中调用了
sGpsInterface->init(&sGpsCallbacks),

frameworks/base/services/core/jni/com_android_server_location_GnssLocationProvider.cpp

{"native_init", "()Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_init)},

 

 

static jboolean android_location_GnssLocationProvider_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 (gnssHal == nullptr) {
        ALOGE("Unable to Initialize GNSS HAL\n");
        return JNI_FALSE;
    }

    sp<IGnssCallback> gnssCbIface = new GnssCallback();

    Return<bool> result = false;
    if (gnssHal_V1_1 != nullptr) {
        result = gnssHal_V1_1->setCallback_1_1(gnssCbIface);
    } else {
        result = gnssHal->setCallback(gnssCbIface);
    }
    if (!result.isOk() || !result) {
        ALOGE("SetCallback for Gnss Interface fails\n");
        return JNI_FALSE;
    }

    sp<IGnssXtraCallback> gnssXtraCbIface = new GnssXtraCallback();
    if (gnssXtraIface == nullptr) {
        ALOGE("Unable to initialize GNSS Xtra interface\n");
    } else {
        result = gnssXtraIface->setCallback(gnssXtraCbIface);
        if (!result.isOk() || !result) {
            gnssXtraIface = nullptr;
            ALOGI("SetCallback for Gnss Xtra Interface fails\n");
        }
    }

    sp<IAGnssCallback> aGnssCbIface = new AGnssCallback();
    if (agnssIface != nullptr) {
        agnssIface->setCallback(aGnssCbIface);
    } else {
        ALOGI("Unable to Initialize AGnss interface\n");
    }

    sp<IGnssGeofenceCallback> gnssGeofencingCbIface = new GnssGeofenceCallback();
    if (gnssGeofencingIface != nullptr) {
      gnssGeofencingIface->setCallback(gnssGeofencingCbIface);
    } else {
        ALOGI("Unable to initialize GNSS Geofencing interface\n");
    }

    sp<IGnssNiCallback> gnssNiCbIface = new GnssNiCallback();
    if (gnssNiIface != nullptr) {
        gnssNiIface->setCallback(gnssNiCbIface);
    } else {
        ALOGI("Unable to initialize GNSS NI interface\n");
    }

    sp<IAGnssRilCallback> aGnssRilCbIface = new AGnssRilCallback();
    if (agnssRilIface != nullptr) {
        agnssRilIface->setCallback(aGnssRilCbIface);
    } else {
        ALOGI("Unable to Initialize AGnss Ril interface\n");
    }

    return JNI_TRUE;
}

 

 

这是将jni的一些函数作为参数传递到native c 空间中去,这样在native c中如果有可用数据将通过回调的方式调用到jni中的函数。简单的看一下 location_callback的定义:

struct GnssCallback : public IGnssCallback {
    Return<void> gnssLocationCb(const GnssLocation& location) override;
    Return<void> gnssStatusCb(const IGnssCallback::GnssStatusValue status) override;
    Return<void> gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override;
    Return<void> gnssNmeaCb(int64_t timestamp, const android::hardware::hidl_string& nmea) override;
    Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override;
    Return<void> gnssAcquireWakelockCb() override;
    Return<void> gnssReleaseWakelockCb() override;
    Return<void> gnssRequestTimeCb() override;
    Return<void> gnssRequestLocationCb(const bool independentFromGnss) override;
    Return<void> gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override;

    // New in 1.1
    Return<void> gnssNameCb(const android::hardware::hidl_string& name) override;

    // TODO(b/73306084): Reconsider allocation cost vs threadsafety on these statics
    static const char* sNmeaString;
    static size_t sNmeaStringLength;
};

 

这是将jni的一些函数作为参数传递到native c 空间中去,这样在native c中如果有可用数据将通过回调的方式调用到jni中的函数。简单的看一下 location_callback的定义:

struct GnssCallback : public IGnssCallback {
    Return<void> gnssLocationCb(const GnssLocation& location) override;
    Return<void> gnssStatusCb(const IGnssCallback::GnssStatusValue status) override;
    Return<void> gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override;
    Return<void> gnssNmeaCb(int64_t timestamp, const android::hardware::hidl_string& nmea) override;
    Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override;
    Return<void> gnssAcquireWakelockCb() override;
    Return<void> gnssReleaseWakelockCb() override;
    Return<void> gnssRequestTimeCb() override;
    Return<void> gnssRequestLocationCb(const bool independentFromGnss) override;
    Return<void> gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override;

    // New in 1.1
    Return<void> gnssNameCb(const android::hardware::hidl_string& name) override;

    // TODO(b/73306084): Reconsider allocation cost vs threadsafety on these statics
    static const char* sNmeaString;
    static size_t sNmeaStringLength;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值