Android GPS学習ノート—GpsLP初期化

8628 ワード

目次:
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プッシュメールを受信すると、checkSmsSuperInitまたはcheckWapSuperInit関数が呼び出されます.この2つの関数の機能は比較的簡単で、メールの内容を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ボリュームを深く理解する』