【Android】GPS启动流程及数据流向分析(基于2.3.5)
GPS启动流程及数据流向分析:
首先在系统init阶段,会通过ServiceManager addService添加很多的Service,这其中就包含LocationService。
代码在SystemServer.java中:
Slog.i(TAG, "Location Manager");
location = new LocationManagerService(context);
ServiceManager.addService(Context.LOCATION_SERVICE, location);
} catch (Throwable e) {
reportWtf("starting Location Manager", e);
}
try {
if (locationF != null) locationF.systemReady();
} catch (Throwable e) {
reportWtf("making Location Service ready", e);
}
// we defer starting up the service until the system is ready
Thread thread = new Thread(null, this, "LocationManagerService");
thread.start();
}
{
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Looper.prepare();
mLocationHandler = new LocationWorkerHandler();
initialize();
Looper.loop();
}
// 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, null,
"(" + Settings.System.NAME + "=?)",
new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
null);
mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mLocationHandler);
SettingsObserver settingsObserver = new SettingsObserver();
mSettings.addObserver(settingsObserver);
}
1) loadProviders(),会new一个GpsLocationProvider,并将本GpsLocationProvider添加一个ArrayList<LocationProviderInterface>的链 表中。
2) new 一个 SettingsObserver对象,该对象应该是负责在Settings中有数据变化时通知本地程序进行相应处理的功能。其中 SettingsObserver类中实现 了Observer接口,该接口中的update函数应该就是一个回调函数,当Settings中有数据变化时会回调进这个函数:
public void update(Observable o, Object arg) {
synchronized (mLock) {
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 = isAllowedBySettingsLocked(name);
If (isEnabled && !shouldBeEnabled) {
updateProviderListenersLocked(name, false);
changesMade = true;
} else if (!isEnabled && shouldBeEnabled) {
updateProviderListenersLocked(name, true);
changesMade = true;
}
}
if (changesMade) {
mContext.sendBroadcast(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION));
}
}
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) {
final int N = records.size();
for (int i=0; i<N; 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<Receiver>();
}
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);
}
} else {
p.enableLocationTracking(false);
p.disable();
}
}
GpsLocationProvider.java
synchronized (mHandler) {
sendMessage(ENABLE, 1, null);
}
}
if (DEBUG) Log.d(TAG, "handleEnable");
if (mEnabled) return;
mEnabled = native_init();
Intent intent = new Intent(LocationManager.GPS_SETTING_ENABLED_CHANGE_ACTION);
intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mEnabled);
mContext.sendBroadcast(intent);
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);
}
} else {
Log.w(TAG, "Failed to enable location provider");
}
}
native_init对应jni中的android_location_GpsLocationProvider_init函数,在该函数中调用了
sGpsInterface->init(&sGpsCallbacks),
而 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,
};
{
JNIEnv* env = AndroidRuntime::getJNIEnv();
env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags,
(jdouble)location->latitude, (jdouble)location->longitude,
(jdouble)location->altitude,
(jfloat)location->speed, (jfloat)location->bearing,
(jfloat)location->accuracy, (jlong)location->timestamp);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
}
其中有定义:
static jmethodID method_reportLocation;并且:
method_reportLocation = env->GetMethodID(clazz, "reportLocation","(IDDDFFFJ)V");
可见jni中的callback函数其实又回调掉了java空间(Framework)中的 reportLocation函数,这便是整个GPS框架的数据流向结构了。所有的数据都是通过回调的方式通知上层:
nativeC通过回调通知JNI,JNI通过回调通知Framework。这应该是gps整个框架最重要的部分吧,理解了数据流向,其他的应该都简单了。
我们的native c中并没有实现 native_set_agps_server的功能,所以使用agps的数据服务器不在上层指定,而是在c文件中直接指定的。 native_set_agps_server只是一个空函数。
上面介绍了 sGpsInterface->init(&sGpsCallbacks)中sGpsCallbacks的作用,但是init函数调用还未进行剖析:
sGpsInterface定义如下:
static const GpsInterface* sGpsInterface = NULL;
它是在android_location_GpsLocationProvider_class_init_native函数初始化的,该函数在GpsLocationProvider中通过static方式预加载:
if (err == 0) {
hw_device_t* device;
//通过open调用,在native层分配了一个 gps_device_t的空间,并传递回来。
err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
if (err == 0) {
//这个强制转换是因为 gps_device_t中第一个item是一个 hw_device_t。
//并且在native中确实是分配的gps_device_t空间
gps_device_t* gps_device = (gps_device_t *)device;
sGpsInterface = gps_device->get_gps_interface(gps_device);
}
}
struct hw_device_t** device)
{
struct gps_device_t *dev = malloc(sizeof(struct gps_device_t));
if (dev == NULL) {
LOGE("gps device can not malloc memery!");
return -ENOMEM;
}
memset(dev, 0, sizeof(*dev));
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 0;
dev->common.module = (struct hw_module_t*)module;
dev->common.close = close_gps;
//注意一个有参 一个无参
dev->get_gps_interface = gps_get_hardware_interface;
*device = (struct hw_device_t *)dev;
return 0;
}
const GpsInterface *gps_get_hardware_interface()
{
return &ubloxGpsInterface;
}
/*gps interface struct*/
static const GpsInterface ubloxGpsInterface =
{
.size = sizeof(GpsInterface),
.init = ublox_gps_init,
.start = ublox_gps_start,
.stop = ublox_gps_stop,
.cleanup = ublox_gps_cleanup,
.inject_location = ublox_gps_inject_location,
.delete_aiding_data = ublox_gps_delete_aiding_data,
.set_position_mode = ublox_gps_set_position_mode,
.get_extension = ublox_gps_get_extension,
};
static int ublox_gps_init(GpsCallbacks* callbacks)
{
UbloxGpsData *gps_data = &ublox_gps_data;
//ublox gps support MS-based A-GPS, fix in the gps terminal
callbacks->set_capabilities_cb(GPS_CAPABILITY_SCHEDULING | GPS_CAPABILITY_MSB);
pthread_mutex_init(&gps_data->deferred_action_mutex, NULL);
pthread_cond_init(&gps_data->deferred_action_cond, NULL);
agps_state->used_proxy = 0;
gps_data->gps_callbacks = *callbacks;
gps_data->thread_start = 0;
LOGD("gps finishes initialization");
return 0;
}
应用层通过调用
resolver,
LocationManager.GPS_PROVIDER,
desiredState);
我这个博客废弃不用了,今天想寻找外链的时候,突然想到这个博客权重很高。
有需要免费外链的,留言即可,我准备把这个博客变成免费的友情链接站点。