Android GPS学习笔记—GpsLP初始化

原创 2015年07月07日 15:13:13

目录:

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卷》


(M)SIM卡开机流程分析之SubscriptionController类分析

首先,看看google对于SubscriptionController类的说明 /** * SubscriptionController to provide an inter-process c...
  • Check_Out
  • Check_Out
  • 2017年03月11日 15:31
  • 1436

《深入理解Android:Wi-Fi,NFC和GPS》章节连载[节选]--第九章 深入理解GPS

首先感谢各位兄弟姐妹们的耐心等待。根据今天得到的消息,本书预计在下周各大网店提供预订。注意,此处连载的是未经出版社编辑的原始稿件,所以样子会有些非专业。注意,如下是本章目录,本文节选9.1~9.2.2...
  • Innost
  • Innost
  • 2014年03月22日 22:17
  • 21902

SUPL技术(一)

[写在前面]3G除了将带来一个宽带、多媒体的无线互联时代之外,其移动性的特点也不容小觑。多媒体业务在2G时代的开展不成功,不外乎网络慢、终端少、资费贵、内容缺这几个方面;而基于位置的服务在2G时代开展...
  • dailinqing1984
  • dailinqing1984
  • 2015年05月19日 10:59
  • 744

Android系统Gps分析(一)

1 GPS架构 2 GPS分析 2.1 头文件 头文件定义在:hardware/libhardware/include/hardware/gps.h,定义了GPS底层相关...
  • xnwyd
  • xnwyd
  • 2012年01月13日 14:49
  • 42347

android 修改gps串口解析

  • 2011年12月07日 18:31
  • 9KB
  • 下载

Android GPS学习笔记—JNI层实现

Android GPS JNI层只有一个文件,起到承上启下的作用。上层承接Framework,下层调用HAL层具体硬件抽象实现。 目录: frameworks/base/services/core/j...
  • dreamback1987
  • dreamback1987
  • 2015年06月19日 14:51
  • 3000

android4.3 GPS定位问题

最近在调试GPS的时候,GPS需要定位很久才能定位到,花费时间几分钟到几十分钟不定。对用户来说,这是无法接受的。使用logcat查看调试信息, 发现串口是有正确的定位信息的,获取不到到GPS数据不完整...
  • bzw73
  • bzw73
  • 2015年03月17日 15:11
  • 2120

Android4.4 GPS框架分析

GPS HAL层代码在目录trunk/Android/hardware/xxx/gps/skytraqskytraq_gsp.c,向下与硬件驱动通讯,向上提供接口 GPS JNI层层代码在目录tru...
  • junzhang1122
  • junzhang1122
  • 2015年06月28日 22:02
  • 1067

Android GPS学习笔记—GpsLP初始化

目录: frameworks\base\services\core\java\com\android\server\location GpsLocationProvider本身有一段初始化代码,如...
  • dreamback1987
  • dreamback1987
  • 2015年07月07日 15:13
  • 1876

Android GPS学习笔记(6)—GpsLP初始化

目录: frameworks\base\services\core\java\com\android\server\location GpsLocationProvider本身有一段初始化代...
  • dailinqing1984
  • dailinqing1984
  • 2015年11月05日 10:01
  • 601
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android GPS学习笔记—GpsLP初始化
举报原因:
原因补充:

(最多只允许输入30个字)