现在的位置: 首页 > 综合 > 正文

GPS 研究二 (Android 2.3__gingerbread)

2013年08月19日 ⁄ 综合 ⁄ 共 17149字 ⁄ 字号 评论关闭
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
Service
NetworkManagement 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<LocationProviderInterface>
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()函数的分析。

抱歉!评论已关闭.