Chinaunix首页 | 论坛 | 博客
  • 博客访问: 14107
  • 博文数量: 3
  • 博客积分: 111
  • 博客等级: 入伍新兵
  • 技术积分: 55
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-22 15:55
文章分类

全部博文(3)

文章存档

2011年(3)

我的朋友

分类: 嵌入式

2011-03-22 18:13:34

JNI层文件
2.2
frameworks/base/core/jni/android_location_GpsLocationProvider.cpp
2.3
/framework/base/services/jni/com_android_server_location_GpsLocationProvider.cpp
 
 
 
 
下面来看看gps的定位服务(LocationManager)的启动过程
 
LocationManager 这项服务是在SystemServer.java 中启动的,也就是系统启动之后,这个服务就已经启动了

SystemServer.javainit2函数中启动了一个线程来注册Android的诸多服务,如:Bluetooth ServiceNetworkManagement ServiceNotification Manager等,当然也包括Location Service

systemServer.java [framework\base\services\java\com\android\server]

  1. public static final void init2() {

  2. Slog.i(TAG, "Entered the Android system server!");

  3. Thread thr = new ServerThread();

  4. thr.setName("android.server.ServerThread");

  5. thr.start();

  6. }

 

ServerThread线程的run函数中LocationManager服务的代码段如下:

  1. try {

  2.                 Slog.i(TAG, "Location Manager");

  3.                 location = new LocationManagerService(context);

  4.                 ServiceManager.addService(Context.LOCATION_SERVICE, location);

  5.             } catch (Throwable e) {

  6.                 Slog.e(TAG, "Failure starting Location Manager", e);
  7. }

 

run函数的后半部分,是服务对系统的反馈,就是systemReady()函数。 LocationManager服务的反馈函数如下:

  1. final LocationManagerService locationF = location;

其中的locationF LocationManagerServicefinal类型,就是一旦赋值,不能更改。

  1. if (locationF != null) locationF.systemReady();

 

下面我们来看看2.3的 LocationManagerService 构造函数。

  1. /**
  2.      * @param context the context that the LocationManagerService runs in
  3.      */
  4.     public LocationManagerService(Context context) {
  5.         super();
  6.         mContext = context;
  7.         Resources resources = context.getResources();
  8.         mNetworkLocationProviderPackageName = resources.getString(
  9.                 com.android.internal.R.string.config_networkLocationProvider);
  10.         mGeocodeProviderPackageName = resources.getString(
  11.                 com.android.internal.R.string.config_geocodeProvider);
  12.         mPackageMonitor.register(context, true);

  13.         if (LOCAL_LOGV) {
  14.             Slog.v(TAG, "Constructed LocationManager Service");
  15.         }
  16.     }

以下为2.2

  1. public LocationManagerService(Context context) {
  2.         super();
  3. mContext = context;
  4.         if (LOCAL_LOGV) {
  5.             Slog.v(TAG, "Constructed LocationManager Service");
  6.         }
  7.     }

 

然后我们再看SystemReady()

  1. void systemReady() {
  2.         // we defer starting up the service until the system is ready

  3.         Thread thread = new Thread(null, this, "LocationManagerService");
  4.         thread.start();
  5.     }

在这个函数当中,我们创建了一个新线程。然后start之。

因此我们的视线也随之跟随到run函数里面。

  1. public void run()
  2.     {
  3.         Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
  4.         Looper.prepare();
  5.         mLocationHandler = new LocationWorkerHandler();
  6.         initialize();
  7.         Looper.loop();
  8.     }

在run函数中,又调用了initialize 函数

  1. private void initialize() {
  2.         // Create a wake lock, needs to be done before calling loadProviders() below

  3.         PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
  4.         mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);

  5.         // Load providers

  6.         loadProviders();

  7.         // Register for Network (Wifi or Mobile) updates

  8.         IntentFilter intentFilter = new IntentFilter();
  9.         intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
  10.         // Register for Package Manager updates

  11.         intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
  12.         intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
  13.         intentFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
  14.         mContext.registerReceiver(mBroadcastReceiver, intentFilter);
  15.         IntentFilter sdFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
  16.         mContext.registerReceiver(mBroadcastReceiver, sdFilter);

  17.         // listen for settings changes

  18.         ContentResolver resolver = mContext.getContentResolver();
  19.         Cursor settingsCursor = resolver.query(Settings.Secure.CONTENT_URI, null,
  20.                 "(" + Settings.System.NAME + "=?)",
  21.                 new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
  22.                 null);
  23.         mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mLocationHandler);
  24.         SettingsObserver settingsObserver = new SettingsObserver();
  25.         mSettings.addObserver(settingsObserver);
  26.     }

 

初始化函数中,最重要的便是 loadProviders()函数。

  1. private void loadProviders() {
  2.         synchronized (mLock) {
  3.             if (sProvidersLoaded) {
  4.                 return;
  5.             }

  6.             // Load providers

  7.             loadProvidersLocked();
  8.             sProvidersLoaded = true;
  9.         }
  10.     }

loadProvidersLocked函数

  1. private void loadProvidersLocked() {
  2.         try {
  3.             _loadProvidersLocked();
  4.         } catch (Exception e) {
  5.             Slog.e(TAG, "Exception loading providers:", e);
  6.         }
  7.     }

_loadProvidersLocked函数

  1. private void _loadProvidersLocked() {
  2.         // Attempt to load "real" providers first

  3.         if (GpsLocationProvider.isSupported()) {
  4.             // Create a gps location provider

  5.             GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);
  6.             mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
  7.             mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
  8.             addProvider(gpsProvider);
  9.             mGpsLocationProvider = gpsProvider;
  10.         }
  11.         ...
  12.         ...
  13.         updateProvidersLocked();
  14.     }

首先,我们看GpsLocationProvider.isSupported 这个函数, 这个函数很重要,我们跟进这个函数可以看到, 因为在这个语句中得到了HAL层的GPS接口GpsInterface。就是通过调用GpsLocationProviderisSupported()函数才调用到gps.cpp[hardware/libhardware_legacy/gps]中的gps_get_interface()。这个isSupported函数才是第一个吃螃蟹的人。(而不是JNI层的init函数,这个下面会提到)。

  1. public static boolean isSupported() {
  2.         return native_is_supported();
  3.     }

函数中只有一句话, 这调用了native方法,既Jni层定义的方法。native_is_supported对应在

framework/base/services/jni/com_android_server_location_GpsLocationProvider.cpp文件中的android_location_GpsLocationProvider_is_supported方法。

  1. static jboolean android_location_GpsLocationProvider_is_supported(JNIEnv* env, jclass clazz) {
  2.     return (sGpsInterface != NULL || get_gps_interface() != NULL);
  3. }

这里的get_gps_interface指的是本文件中

  1. static const GpsInterface* get_gps_interface() {
  2.     int err;
  3.     hw_module_t* module;
  4.     const GpsInterface* interface = NULL;

  5.     err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
  6.     if (err == 0) {
  7.         hw_device_t* device;
  8.         err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
  9.         if (err == 0) {
  10.             gps_device_t* gps_device = (gps_device_t *)device;
  11.             interface = gps_device->get_gps_interface(gps_device);
  12.         }
  13.     }

  14.     return interface;
  15. }

而在该get_gps_interface中,去打开模组,之后打开设备,然后通过设备区调用HAL层中的get_gps_interface(gps_device)。

在gps.c(hardware\qcom\gps\loc_api\libloc_api)文件中实现的gps__get_gps_interface调用了loc_eng.cpp里面的 get_gps_interface 接口。

  1. extern "C" const GpsInterface* get_gps_interface()
  2. {
  3.     return &sLocEngInterface;
  4. }
  1. static const GpsInterface sLocEngInterface =
  2. {
  3.     sizeof(GpsInterface),
  4.     loc_eng_init,
  5.     loc_eng_start,
  6.     loc_eng_stop,
  7.     loc_eng_cleanup,
  8.     loc_eng_inject_time,
  9.     loc_eng_inject_location,
  10.     loc_eng_delete_aiding_data,
  11.     loc_eng_set_position_mode,
  12.     loc_eng_get_extension,
  13. };

到这里为止, 一句简单的isSupported()执行的内容终于告一段落了。 我们获取到了GPS 的接口。在上面的LocationManagerService.java中, 如果找到gps硬件,并获取了接口则我们据悉执行isSupported()的下一句。

  1. GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);

注意GpsLocationProvider构造函数里面的两个参数:mContext, this。下面来看看GpsLocationProvider的构造函数的前面几句:

  1. public GpsLocationProvider(Context context, ILocationManager locationManager) {
  2.         mContext = context;
  3.         mLocationManager = locationManager;
  4.         mNIHandler = new GpsNetInitiatedHandler(context, this);

  5.        ...

  6. }
GpsLocationProvider类里面的成员变量mLocationManager是构造函数的第二个参数,就是说是LocationManagerService对象。这一点在这里先明确。
 

接着看_loadProvidersLocked函数。

 

  1. private void _loadProvidersLocked() {
  2.         // Attempt to load "real" providers first

  3.         if (GpsLocationProvider.isSupported()) {
  4.             // Create a gps location provider

  5.             GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);
  6.             mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
  7.             mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
  8.             addProvider(gpsProvider);
  9.             mGpsLocationProvider = gpsProvider;
  10.         }

  11.         // create a passive location provider, which is always enabled

  12.         PassiveProvider passiveProvider = new PassiveProvider(this);
  13.         addProvider(passiveProvider);
  14.         mEnabledProviders.add(passiveProvider.getName());

  15.         // initialize external network location and geocoder services

  16.         if (mNetworkLocationProviderPackageName != null) {
  17.             mNetworkLocationProvider =
  18.                 new LocationProviderProxy(mContext, LocationManager.NETWORK_PROVIDER,
  19.                         mNetworkLocationProviderPackageName, mLocationHandler);
  20.             addProvider(mNetworkLocationProvider);
  21.         }

  22.         if (mGeocodeProviderPackageName != null) {
  23.             mGeocodeProvider = new GeocoderProxy(mContext, mGeocodeProviderPackageName);
  24.         }

  25.         updateProvidersLocked();
  26.     }

在构造完GpsLocationProvider之后将其add到全局变量ArrayList mProviders中,备以后调用。

PassiveProvider暂时未了解到其用意。

然后启动了nerwork location和geocoder 两个service。但是可惜的是这两个服务都无法启动,因为他们是通过配置文件conifg.xml [framework\base\core\res\res\values]得到服务的名字,然后启动服务的。但是在这个配置文件中,两个服务的名字都是null

conifg.xml [framework\base\core\res\res\values]

<!-- Component name of the service providing network location support. -->
    <string name="config_networkLocationProvider">@null</string>
    <!-- Component name of the service providing geocoder API support. -->
    <string name="config_geocodeProvider">@null</string>

其实这也导致了,在调用GetFromLocationName和GetFromLocation两个函数时提示“Service not Available”,这个是google Android 2.2中就存在的bug。

_loadProvidersLocked函数的最后一句是调用updateProvidersLocked函数,仍然在LocationManagerServic.java文件中。

2.3:

  1. private void updateProvidersLocked() {
  2.         boolean changesMade = false;
  3.         for (int i = mProviders.size() - 1; i >= 0; i--) {
  4.             LocationProviderInterface p = mProviders.get(i);
  5.             boolean isEnabled = p.isEnabled();
  6.             String name = p.getName();
  7.             boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
  8.             if (isEnabled && !shouldBeEnabled) {
  9.                 updateProviderListenersLocked(name, false);
  10.                 changesMade = true;
  11.             } else if (!isEnabled && shouldBeEnabled) {
  12.                 updateProviderListenersLocked(name, true);
  13.                 changesMade = true;
  14.             }
  15.         }
  16.         if (changesMade) {
  17.             mContext.sendBroadcast(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION));
  18.         }
  19.     }

依靠前面的代码我们可以推测在mProviders里面应该存在一个gpsProvider 和PassiveProvider,而gpsProvider是未被enable的。而passiveProvider是enable的。

这边我们对gpsProvider进行讨论,他执行的是updateProviderListenersLocked(name,true) 然后当有发生改变,就是changesMade=true时,它发送了广播,内容是告诉大家LocationManager发生了变化,让需要的接收者自己接收。

 

下面我们跟进updateProviderListenersLocked(name,true)函数。

在LocationManagerService.java文件中

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

  3.         LocationProviderInterface p = mProvidersByName.get(provider);
  4.         if (p == null) {
  5.             return;
  6.         }

  7.         ArrayList<Receiver> deadReceivers = null;
  8.         
  9.         ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
  10.         if (records != null) {
  11.             final int N = records.size();
  12.             for (int i=0; i<N; i++) {
  13.                 UpdateRecord record = records.get(i);
  14.                 // Sends a notification message to the receiver

  15.                 if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
  16.                     if (deadReceivers == null) {
  17.                         deadReceivers = new ArrayList<Receiver>();
  18.                     }
  19.                     deadReceivers.add(record.mReceiver);
  20.                 }
  21.                 listeners++;
  22.             }
  23.         }

  24.         if (deadReceivers != null) {
  25.             for (int i=deadReceivers.size()-1; i>=0; i--) {
  26.                 removeUpdatesLocked(deadReceivers.get(i));
  27.             }
  28.         }
  29.         
  30.         if (enabled) {
  31.             p.enable();
  32.             if (listeners > 0) {
  33.                 p.setMinTime(getMinTimeLocked(provider), mTmpWorkSource);
  34.                 p.enableLocationTracking(true);
  35.             }
  36.         } else {
  37.             p.enableLocationTracking(false);
  38.             p.disable();
  39.         }
  40.     }

这边我们看if(enable)内的主题部分。 enable为真, 则启动了GPS服务。然后执行p.enable()函数。

enable()函数在GPSLocationProvider.java中

  1. /**
  2.      * Enables this provider. When enabled, calls to getStatus()
  3.      * must be handled. Hardware may be started up
  4.      * when the provider is enabled.
  5.      */
  6.     public void enable() {
  7.         synchronized (mHandler) {
  8.             sendMessage(ENABLE, 1, null);
  9.         }
  10.     }
  1. private void sendMessage(int message, int arg, Object obj) {
  2.         // hold a wake lock while messages are pending

  3.         synchronized (mWakeLock) {
  4.             mPendingMessageBits |= (1 << message);
  5.             mWakeLock.acquire();
  6.             mHandler.removeMessages(message);
  7.             Message m = Message.obtain(mHandler, message);
  8.             m.arg1 = arg;
  9.             m.obj = obj;
  10.             mHandler.sendMessage(m);
  11.         }
  12.     }

我们看到enable函数中只是调用了sendMessage。 跟进函数,可看到sendMessage函数,首先做的是把相关的消息标志位给设置位。而后获取mWakeLock ?这边有点疑问,之前进入本段代码的时候不是获取了mWakeLock了? 然后将上一次的相关消息删除,重新构造心的消息,让后发送给mHandler。

收到消息后,Hnadler会自动去调用handleMessage去处理收到的消息。

  1. public void handleMessage(Message msg) {
  2.             int message = msg.what;
  3.             switch (message) {
  4.                 case ENABLE:
  5.                     if (msg.arg1 == 1) {
  6.                         handleEnable();
  7.                     } else {
  8.                         handleDisable();
  9.                     }
  10.                     break;
  11. ...

根据构造的消息,我们将执行hanleEnable()。

  1. private void handleEnable() {
  2.         if (DEBUG) Log.d(TAG, "handleEnable");
  3.         if (mEnabled) return;
  4.         mEnabled = native_init();

  5.         if (mEnabled) {
  6.             mSupportsXtra = native_supports_xtra();
  7.             if (mSuplServerHost != null) {
  8.                 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
  9.             }
  10.             if (mC2KServerHost != null) {
  11.                 native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
  12.             }
  13.         } else {
  14.             Log.w(TAG, "Failed to enable location provider");
  15.         }
  16.     }

这边handleEnable函数主要做了两件事。

1.调用JNI层的native_init()方法去初始化GPS。

2.试图启动agps服务。

我们先看第一件事。在com_android_server_location_GPSLocationProvider.cpp可以找到JNI层的相关实现

  1. static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj)
  2. {
  3.     const GpsInterface* interface = GetGpsInterface(env, obj);
  4.     if (!interface)
  5.         return false;

  6.     if (!sGpsDebugInterface)
  7.        sGpsDebugInterface = (const GpsDebugInterface*)interface->get_extension(GPS_DEBUG_INTERFACE);

  8.     return true;
  9. }

这边调用了GetGpsInterface去获取接口并初始化GPS。 后半部分试图去调用其相关的扩展接口。

  1. static const GpsInterface* GetGpsInterface(JNIEnv* env, jobject obj) {
  2.     // this must be set before calling into the HAL library

  3.     if (!mCallbacksObj)
  4.         mCallbacksObj = env->NewGlobalRef(obj);

  5.     if (!sGpsInterface) {
  6.         sGpsInterface = get_gps_interface();
  7.         if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0) {
  8.             sGpsInterface = NULL;
  9.             return NULL;
  10.         }
  11.     }
  12.     return sGpsInterface;
  13. }

GetGpsInterface里面也去调用了get_gps_interface(),而这个函数前面也有提到,最早的地方便是isSupported()的这个函数。在获取了这个接口之后,使用sGpsInterface->init函数进行了初始化。

在gps_qemu.c中(模拟器中)

  1. static int
  2. qemu_gps_init(GpsCallbacks* callbacks)
  3. {
  4.     GpsState* s = _gps_state;

  5.     if (!s->init)
  6.         gps_state_init(s);

  7.     if (s->fd < 0)
  8.         return -1;

  9.     s->callbacks = *callbacks;

  10.     return 0;
  11. }

这边qemu_gps_init函数即是sGpsInterface->init函数,其中里面做了gps_state_init初始化,并注册了callbacks回调函数,而这个函数也是在JNI层实现的,而且有JNI层传下来的函数。

  1. static void
  2. gps_state_init( GpsState* state )
  3. {
  4.     state->init = 1;
  5.     state->control[0] = -1;
  6.     state->control[1] = -1;
  7.     state->fd = -1;

  8.     state->fd = qemud_channel_open(QEMU_CHANNEL_NAME);

  9.     if (state->fd < 0) {
  10.         D("no gps emulation detected");
  11.         return;
  12.     }

  13.     D("gps emulation will read from '%s' qemud channel", QEMU_CHANNEL_NAME );

  14.     if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, state->control ) < 0 ) {
  15.         LOGE("could not create thread control socket pair: %s", strerror(errno));
  16.         goto Fail;
  17.     }

  18.     if ( pthread_create( &state->thread, NULL, gps_state_thread, state ) != 0 ) {
  19.         LOGE("could not create gps thread: %s", strerror(errno));
  20.         goto Fail;
  21.     }

  22.     D("gps state initialized");
  23.     return;

  24. Fail:
  25.     gps_state_done( state );
  26. }

在这个gps_state_init函数中,首先打开串口,然后建立socket通信,然后建立线程监听底层数据上报,分别对应于代码中黄低部分。

我们顺便看到qemu_gps_get_extension 函数,

  1. static const void*
  2. qemu_gps_get_extension(const char* name)
  3. {
  4.     // no extensions supported

  5.     return NULL;
  6. }

这是一个空函数,说明初始化的时候调用的相关扩展接口是没有用的。

在Android2.2中,handleEnable还做了一件事情,就是创建了一个监听线程 。

 而android2.3中,在GPSlocationProvider构造的时候就创建了一个线程。

  1. public GpsLocationProvider(Context context, ILocationManager locationManager) {
  2.   
  3.         ... ...
  4.         // wait until we are fully initialized before returning

  5.         mThread = new GpsLocationProviderThread();
  6.         mThread.start();
  7.         while (true) {
  8.             try {
  9.                 mInitializedLatch.await();
  10.                 break;
  11.             } catch (InterruptedException e) {
  12.                 Thread.currentThread().interrupt();
  13.             }
  14.         }
  15.     }

查看run函数相关内容:

  1. public void run() {
  2.             Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
  3.             initialize();
  4.             Looper.prepare();
  5.             mHandler = new ProviderHandler();
  6.             // signal when we are initialized and ready to go

  7.             mInitializedLatch.countDown();
  8.             Looper.loop();
  9.         }

run函数去调用了 initialize初始化函数,然后新建一个looper,新建一个providerHandler 用于处理该线程的消息。然后看是否初始化完成。然后进入消息循环,准备收发,处理消息。

  1. private void initialize() {
  2.         // register our receiver on our thread rather than the main thread
  1.         IntentFilter intentFilter = new IntentFilter();
  2.         intentFilter.addAction(ALARM_WAKEUP);
  3.         intentFilter.addAction(ALARM_TIMEOUT);
  4.         mContext.registerReceiver(mBroadcastReciever, intentFilter);
  5.     }

初始化主要是将线程的接收者注册到我们的线程上,而不是注册到主线程上。

到这边为止我们完成了 p.enable()函数的分析。

阅读(3543) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:GPS 研究三 (android2.3__gingerbread)

给主人留下些什么吧!~~