Android GPS学习笔记—GpsLP初始化
16lz
2021-01-23
目录:
frameworks\base\services\core\java\com\android\server\location
GpsLocationProvider本身有一段初始化代码,如下所示:
//GpsLP定义了一些native函数,此处的class_init_native将初始化相关JNI方法static { class_init_native(); }
下面看一下GpsLocationProvider的构造函数:
public GpsLocationProvider(Context context, ILocationManager ilocationManager, Looper looper) { mContext = context; /** NTP即Network Time Protocol,它是一种用来同步计算机时间的协议。该时间的源是UTC。在下面这行代码中,GpsLP将创建一个NtpTrustedTime对象,该对象采用SNTP协议来和指定的NTP服务器通信以获取准确的时间。 **/ mNtpTime = NtpTrustedTime.getInstance(context); mILocationManager = ilocationManager; mLocation.setExtras(mLocationExtras); // Create a wake lock mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY); mWakeLock.setReferenceCounted(true); mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0); mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0); mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); // App ops service to keep track of who is accessing the GPS mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService( Context.APP_OPS_SERVICE)); // Battery statistics service to be notified when GPS turns on or off mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService( BatteryStats.SERVICE_NAME)); // 加载GPS配置文件,下文详细介绍函数reloadGpsProperties mProperties = new Properties(); reloadGpsProperties(mContext, mProperties); // 主要处理来自GPS HAL层通知的NI事件 mNIHandler = new GpsNetInitiatedHandler(context, mNetInitiatedListener, mSuplEsEnabled); // construct handler, listen for events mHandler = new ProviderHandler(looper); //SUPL的初始化可以由两种特殊的短信触发,下文将简单介绍listenForBroadcasts函数 listenForBroadcasts(); // 对PASSIVE_PROVIDER添加监听 mHandler.post(new Runnable() { @Override public void run() { LocationManager locManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); final long minTime = 0; final float minDistance = 0; final boolean oneShot = false; LocationRequest request = LocationRequest.createFromDeprecatedProvider( LocationManager.PASSIVE_PROVIDER, minTime, minDistance, oneShot); request.setHideFromAppOps(true); //接收来自NetworkLP的位置更新通知 //当GpsLP收到来自NetworkLP的位置信息后,将把他们传给GPS HAL层去处理 locManager.requestLocationUpdates( request, new NetworkLocationListener(), mHandler.getLooper()); } }); }函数reloadGpsProperties从文件etc/gps.conf中加载了GPS相关参数包括SUPL服务器地址、端口号等,代码如下:
private void reloadGpsProperties(Context context, Properties properties) { Log.d(TAG, "Reset GPS properties, previous size = " + properties.size()); loadPropertiesFromResource(context, properties); boolean isPropertiesLoadedFromFile = false; final String gpsHardware = SystemProperties.get("ro.hardware.gps"); if (!TextUtils.isEmpty(gpsHardware)) { final String propFilename = PROPERTIES_FILE_PREFIX + "." + gpsHardware + PROPERTIES_FILE_SUFFIX; isPropertiesLoadedFromFile = loadPropertiesFromFile(propFilename, properties); } //加载文件中的GPS属性信息 if (!isPropertiesLoadedFromFile) { loadPropertiesFromFile(DEFAULT_PROPERTIES_FILE, properties); } Log.d(TAG, "GPS properties reloaded, size = " + properties.size()); // 读取配置文件中的属性信息,通过JNI设置到HAL层 setSuplHostPort(properties.getProperty("SUPL_HOST"), properties.getProperty("SUPL_PORT")); //C2K是CDMA2000的缩写,C2K_HOST和C2K_PORT主要用于GPS模块的测试,对用户来说没有太大意义 mC2KServerHost = properties.getProperty("C2K_HOST"); String portString = properties.getProperty("C2K_PORT"); if (mC2KServerHost != null && portString != null) { try { mC2KServerPort = Integer.parseInt(portString); } catch (NumberFormatException e) { Log.e(TAG, "unable to parse C2K_PORT: " + portString); } } try { // Convert properties to string contents and send it to HAL. ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); properties.store(baos, null); native_configuration_update(baos.toString()); Log.d(TAG, "final config = " + baos.toString()); } catch (IOException ex) { Log.w(TAG, "failed to dump properties contents"); } // SUPL_ES configuration. String suplESProperty = mProperties.getProperty("SUPL_ES"); if (suplESProperty != null) { try { mSuplEsEnabled = (Integer.parseInt(suplESProperty) == 1); } catch (NumberFormatException e) { Log.e(TAG, "unable to parse SUPL_ES: " + suplESProperty); } } }下面我们来看一下listenForBroadcasts函数,其内容如下:
private void listenForBroadcasts() { IntentFilter intentFilter = new IntentFilter(); //SUPL INIT流程可以由一条特殊的数据短信触发。数据短信与文本短信不同,下面的这个IntentFilter将接收发往 //127.0.0.1的数据短信。7275为OMA-SUPL使用的端口号 intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION); intentFilter.addDataScheme("sms"); intentFilter.addDataAuthority("localhost","7275"); mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, mHandler); //SUPL INIT也可由WAP推送短信触发,该短信包含的数据类型为MIME中的"application/vnd.omaloc-supl-init" intentFilter = new IntentFilter(); intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION); try { intentFilter.addDataType("application/vnd.omaloc-supl-init"); } catch (IntentFilter.MalformedMimeTypeException e) { Log.w(TAG, "Malformed SUPL init mime type"); } mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, mHandler); //监听ALARM事件、网络事件等 intentFilter = new IntentFilter(); intentFilter.addAction(ALARM_WAKEUP); intentFilter.addAction(ALARM_TIMEOUT); intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED); intentFilter.addAction(Intent.ACTION_SCREEN_OFF); intentFilter.addAction(Intent.ACTION_SCREEN_ON); intentFilter.addAction(SIM_STATE_CHANGED); // TODO: remove the use TelephonyIntents. We are using it because SIM_STATE_CHANGED // is not reliable at the moment. intentFilter.addAction(TelephonyIntents.ACTION_SUBINFO_CONTENT_CHANGE); intentFilter.addAction(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED); mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, mHandler); }当GpsLP收到指定的数据短信或WAP推送短信后,checkSmsSuplInit或checkWapSuplInit函数将被调用。这两个函数的功能比较简单,就是将短信的内容传递到GPS HAL层,下面是它们的代码:
private void checkSmsSuplInit(Intent intent) { SmsMessage[] messages = Intents.getMessagesFromIntent(intent); for (int i=0; i <messages.length; i++) { byte[] supl_init = messages[i].getUserData(); native_agps_ni_message(supl_init,supl_init.length); } } private void checkWapSuplInit(Intent intent) { byte[] supl_init = (byte[]) intent.getExtra("data"); native_agps_ni_message(supl_init,supl_init.length); }GpsLP初始化完毕。
参考文献:《深入理解Android:WiFi、NFC和GPS卷》
更多相关文章
- Android开发傻瓜入门-开发自己的手机短信发送程序
- Android UI架构(四)--SurfaceFlinger的初始化.md
- Android(java)学习笔记86:案例短信发送器
- android 在新建短信时,加入名称为","(英文逗号)的联系人时,应用崩
- Android调用系统短信功能发送短信
- 浅谈android系统java调用C++函数传参过程
- Android 的AT命令协议栈初始化
- Android 短信数据库详细总结分析