GPS 研究三 (android2.3__gingerbread)

LocationManageService.java中
 
  1. private void updateProviderListenersLocked(String provider, boolean enabled) {
  2.            ... ...
  3.         if (enabled) {
  4.             p.enable();
  5.             if (listeners > 0) {
  6.                 p.setMinTime(getMinTimeLocked(provider), mTmpWorkSource);
  7.                 p.enableLocationTracking(true);
  8.             }
  9.         } else {
  10.             p.enableLocationTracking(false);
  11.             p.disable();
  12.         }
  13.     }

接上, 我们研究完了p.enable函数。接下去 如果有listeners ,我们去调用 p.enableLocationTracking()函数。

enableLocationTracking 在GPSLocationProvider.java中。

  1. public void enableLocationTracking(boolean enable) {
  2.         // FIXME - should set a flag here to avoid race conditions with single shot request
  3.         synchronized (mHandler) {
  4.             sendMessage(ENABLE_TRACKING, (enable ? 1 : 0), null);
  5.         }
  6.     }
  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.                 case ENABLE_TRACKING:
  12.                     handleEnableLocationTracking(msg.arg1 == 1);
  13.                     break;
  1. private void handleEnableLocationTracking(boolean enable) {
  2.         if (enable) {
  3.             mTTFF = 0;
  4.             mLastFixTime = 0;
  5.             startNavigating(false);
  6.         } else {
  7.             if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
  8.                 mAlarmManager.cancel(mWakeupIntent);
  9.                 mAlarmManager.cancel(mTimeoutIntent);
  10.             }
  11.             stopNavigating();
  12.         }
  13.     }
  1. private void startNavigating(boolean singleShot) {
  2.         if (!mStarted) {
  3.             if (DEBUG) Log.d(TAG, "startNavigating");
  4.             mStarted = true;
  5.             mSingleShot = singleShot;
  6.             mPositionMode = GPS_POSITION_MODE_STANDALONE;
  7.              if (Settings.Secure.getInt(mContext.getContentResolver(),
  8.                     Settings.Secure.ASSISTED_GPS_ENABLED, 1) != 0) {
  9.                 if (singleShot && hasCapability(GPS_CAPABILITY_MSA)) {
  10.                     mPositionMode = GPS_POSITION_MODE_MS_ASSISTED;
  11.                 } else if (hasCapability(GPS_CAPABILITY_MSB)) {
  12.                     mPositionMode = GPS_POSITION_MODE_MS_BASED;
  13.                 }
  14.             }
  15.             int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
  16.             if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
  17.                     interval, 0, 0)) {
  18.                 mStarted = false;
  19.                 Log.e(TAG, "set_position_mode failed in startNavigating()");
  20.                 return;
  21.             }
  22.             if (!native_start()) {
  23.                 mStarted = false;
  24.                 Log.e(TAG, "native_start failed in startNavigating()");
  25.                 return;
  26.             }
  27.             // reset SV count to zero
  28.             updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
  29.             mFixRequestTime = System.currentTimeMillis();
  30.             if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
  31.                 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
  32.                 // and our fix interval is not short
  33.                 if (mFixInterval >= NO_FIX_TIMEOUT) {
  34.                     mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
  35.                             SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
  36.                 }
  37.             }
  38.         }
  39.     }

这边我中主要关注两个native函数。native_set_position_mode 和native_start!

在com_android_server_location_GpslocationProvider.cpp中找到两个对应的函数。

首先是native_set_position_mode:

  1. static jboolean android_location_GpsLocationProvider_set_position_mode(JNIEnv* env, jobject obj,
  2.         jint mode, jint recurrence, jint min_interval, jint preferred_accuracy, jint preferred_time)
  3. {
  4.     const GpsInterface* interface = GetGpsInterface(env, obj);
  5.     if (interface)
  6.         return (interface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy,
  7.                 preferred_time) == 0);
  8.     else
  9.         return false;
  10. }

这边调用了interface->set_position_mode。我们到gps_qemu.c当中去找其相关实现

  1. static int qemu_gps_set_position_mode(GpsPositionMode mode, int fix_frequency)
  2. {
  3.     // FIXME - support fix_frequency
  4.     return 0;
  5. }

显然其中没有相关的实现。

接下去我们看native_start函数。

  1. static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject obj)
  2. {
  3.     const GpsInterface* interface = GetGpsInterface(env, obj);
  4.     if (interface)
  5.         return (interface->start() == 0);
  6.     else
  7.         return false;
  8. }
  1. static int qemu_gps_start()
  2. {
  3.     GpsState* s = _gps_state;
  4.     if (!s->init) {
  5.         D("%s: called with uninitialized state !!", __FUNCTION__);
  6.         return -1;
  7.     }
  8.     D("%s: called", __FUNCTION__);
  9.     gps_state_start(s);
  10.     return 0;
  11. }
通过向底层发送命令,CMD_START来启动gps。其实这个所谓的底层就是在enable/init函数中启动的等待数据的线程。
  1. static void
  2. gps_state_start( GpsState* s )
  3. {
  4.     char cmd = CMD_START;
  5.     int ret;
  6.     do { ret=write( s->control[0], &cmd, 1 ); }
  7.     while (ret < 0 && errno == EINTR);
  8.     if (ret != 1)
  9.         D("%s: could not send CMD_START command: ret=%d: %s",
  10.           __FUNCTION__, ret, strerror(errno));
  11. }

数据监听线程

  1. /* this is the main thread, it waits for commands from gps_state_start/stop and,
  2.  * when started, messages from the QEMU GPS daemon. these are simple NMEA sentences
  3.  * that must be parsed to be converted into GPS fixes sent to the framework
  4.  */
  5. static void*
  6. gps_state_thread( void* arg )
  7. {
  8.     GpsState* state = (GpsState*) arg;
  9.     NmeaReader reader[1];
  10.     int epoll_fd = epoll_create(2);
  11.     int started = 0;
  12.     int gps_fd = state->fd;
  13.     int control_fd = state->control[1];
  14.     nmea_reader_init( reader );
  15.     // register control file descriptors for polling
  16.     epoll_register( epoll_fd, control_fd );
  17.     epoll_register( epoll_fd, gps_fd );
  18.     D("gps thread running");
  19.     // now loop
  20.     for (;;) {
  21.         struct epoll_event events[2];
  22.         int ne, nevents;
  23.         nevents = epoll_wait( epoll_fd, events, 2, -1 );
  24.         if (nevents < 0) {
  25.             if (errno != EINTR)
  26.                 LOGE("epoll_wait() unexpected error: %s", strerror(errno));
  27.             continue;
  28.         }
  29.         D("gps thread received %d events", nevents);
  30.         for (ne = 0; ne < nevents; ne++) {
  31.             if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0) {
  32.                 LOGE("EPOLLERR or EPOLLHUP after epoll_wait() !?");
  33.                 goto Exit;
  34.             }
  35.             if ((events[ne].events & EPOLLIN) != 0) {
  36.                 int fd = events[ne].data.fd;
  37.                 if (fd == control_fd)
  38.                 {
  39.                     char cmd = 255;
  40.                     int ret;
  41.                     D("gps control fd event");
  42.                     do {
  43.                         ret = read( fd, &cmd, 1 );
  44.                     } while (ret < 0 && errno == EINTR);
  45.                     if (cmd == CMD_QUIT) {
  46.                         D("gps thread quitting on demand");
  47.                         goto Exit;
  48.                     }
  49.                     else if (cmd == CMD_START) {
  50.                         if (!started) {
  51.                             D("gps thread starting location_cb=%p", state->callbacks.location_cb);
  52.                             started = 1;
  53.                             nmea_reader_set_callback( reader, state->callbacks.location_cb );
  54.                         }
  55.                     }
  56.                     else if (cmd == CMD_STOP) {
  57.                         if (started) {
  58.                             D("gps thread stopping");
  59.                             started = 0;
  60.                             nmea_reader_set_callback( reader, NULL );
  61.                         }
  62.                     }
  63.                 }
  64.                 else if (fd == gps_fd)
  65.                 {
  66.                     char buff[32];
  67.                     D("gps fd event");
  68.                     for (;;) {
  69.                         int nn, ret;
  70.                         ret = read( fd, buff, sizeof(buff) );
  71.                         if (ret < 0) {
  72.                             if (errno == EINTR)
  73.                                 continue;
  74.                             if (errno != EWOULDBLOCK)
  75.                                 LOGE("error while reading from gps daemon socket: %s:", strerror(errno));
  76.                             break;
  77.                         }
  78.                         D("received %d bytes: %.*s", ret, ret, buff);
  79.                         for (nn = 0; nn < ret; nn++)
  80.                             nmea_reader_addc( reader, buff[nn] );
  81.                     }
  82.                     D("gps fd event end");
  83.                 }
  84.                 else
  85.                 {
  86.                     LOGE("epoll_wait() returned unkown fd %d ?", fd);
  87.                 }
  88.             }
  89.         }
  90.     }
  91. Exit:
  92.     return NULL;
  93. }

这个监听线程最主要的一个就是nmea_reader_set_callback( )函数

其实就是注册了一个回调函数,location_cb 这个回调函数就是对底层location数据上报的回调函数。

 

到此

enableLocationTracking函数完成了,

也就是LocationManageService.java中

updateProviderListenersLocked的完成

也就是updateProvidersLocked的完成,

也就是loadProviders函数的完成

也就是 initialize的完成,

也就是run的完成,

也就是systemReady的完成

所以完了

你可能感兴趣的:(thread,android,cmd,callback,interface,events)