首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Android GPS学习 (一) :GPS 启动流程

一、Settings

打开GPS的方法往数据库里面写值,然后framework层读取值再做相应处理。

packages/apps/Settings/src/com/android/settings/location/LocationSwitchBarController.java

public void onSwitchChanged(Switch switchView, boolean isChecked) {
    mLocationEnabler.setLocationEnabled(isChecked);
}

/packages/apps/Settings/src/com/android/settings/location/LocationEnabler.java

void setLocationMode(int mode) {
    final int currentMode = Settings.Secure.getInt(mContext.getContentResolver(),
            Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
    if (isRestricted()) {
        // Location toggling disabled by user restriction. Read the current location mode to
        // update the location master switch.
        if (Log.isLoggable(TAG, Log.INFO)) {
            Log.i(TAG, "Restricted user, not setting location mode");
        }
        if (mListener != null) {
            mListener.onLocationModeChanged(currentMode, true);
        }
        return;
    }

    updateLocationMode(mContext, currentMode, mode, ActivityManager.getCurrentUser(),
            Settings.Secure.LOCATION_CHANGER_SYSTEM_SETTINGS);
    refreshLocationMode();
}

二、framework

LocationManagerService的systemRunning方法中会监听setting数据库中的location_providers_allowed字段值的变化,

/frameworks/base/services/core/java/com/android/server/LocationManagerService.java

// listen for settings changes
mContext.getContentResolver().registerContentObserver(
        Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
        new ContentObserver(mLocationHandler) {
            @Override
            public void onChange(boolean selfChange) {
                synchronized (mLock) {
                    updateProvidersLocked();
                }
            }
        }, UserHandle.USER_ALL);

如果该值有变化,则调用updateProvidersLocked方法。

private void updateProvidersLocked() {
    boolean changesMade = false;
    for (int i = mProviders.size() - 1; i >= 0; i--) {
        LocationProviderInterface p = mProviders.get(i);
        boolean isEnabled = p.isEnabled();
        String name = p.getName();
        boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
        if (isEnabled && !shouldBeEnabled) {
            updateProviderListenersLocked(name, false);
            mLastLocation.clear();
            mLastLocationCoarseInterval.clear();
            changesMade = true;
        } else if (!isEnabled && shouldBeEnabled) {
            updateProviderListenersLocked(name, true);
            changesMade = true;
        }
    }
    if (changesMade) {
        mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
                UserHandle.ALL);
        mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
                UserHandle.ALL);
    }
}

在updateProvidersLocked方法中,如果支持gps,调用updateProviderListenersLocked方法。

private void updateProviderListenersLocked(String provider, boolean enabled) {
    int listeners = 0;

    LocationProviderInterface p = mProvidersByName.get(provider);
    if (p == null) return;

    ArrayList<Receiver> deadReceivers = null;

    ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
    if (records != null) {
        for (UpdateRecord record : records) {
            if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
                // Sends a notification message to the receiver
                if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
                    if (deadReceivers == null) {
                        deadReceivers = new ArrayList<>();
                    }
                    deadReceivers.add(record.mReceiver);
                }
                listeners++;
            }
        }
    }

    if (deadReceivers != null) {
        for (int i = deadReceivers.size() - 1; i >= 0; i--) {
            removeUpdatesLocked(deadReceivers.get(i));
        }
    }

    if (enabled) {
        p.enable();
        if (listeners > 0) {
            applyRequirementsLocked(provider);
        }
    } else {
        p.disable();
    }
}

GnssLocationProvider的enable方法如下:

/frameworks/base/services/core/java/com/android/server/location/GnssLocationProvider.java

GnssLocationProvider的enable方法如下:

public void enable() {
    synchronized (mLock) {
        if (mEnabled) return;
        mEnabled = true;
    }

    sendMessage(ENABLE, 1, null);
}

handlenable就是ENABLE的消息处理函数:

private void handleEnable() {
    if (DEBUG) Log.d(TAG, "handleEnable");

    boolean enabled = native_init();

    if (enabled) {
        mSupportsXtra = native_supports_xtra();

        // TODO: remove the following native calls if we can make sure they are redundant.
        if (mSuplServerHost != null) {
            native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
        }
        if (mC2KServerHost != null) {
            native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
        }

        mGnssMeasurementsProvider.onGpsEnabledChanged();
        mGnssNavigationMessageProvider.onGpsEnabledChanged();
        mGnssBatchingProvider.enable();
    } else {
        synchronized (mLock) {
            mEnabled = false;
        }
        Log.w(TAG, "Failed to enable location provider");
    }
}

三、HAL

native_init对应jni中的android_location_GpsLocationProvider_init函数,在该函数中调用了 sGpsInterface->init(&sGpsCallbacks),

frameworks/base/services/core/jni/com_android_server_location_GnssLocationProvider.cpp

{"native_init", "()Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_init)},
static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj) {
    /*
     * This must be set before calling into the HAL library.
     */
    if (!mCallbacksObj)
        mCallbacksObj = env->NewGlobalRef(obj);

    /*
     * Fail if the main interface fails to initialize
     */
    if (gnssHal == nullptr) {
        ALOGE("Unable to Initialize GNSS HAL\n");
        return JNI_FALSE;
    }

    sp<IGnssCallback> gnssCbIface = new GnssCallback();

    Return<bool> result = false;
    if (gnssHal_V1_1 != nullptr) {
        result = gnssHal_V1_1->setCallback_1_1(gnssCbIface);
    } else {
        result = gnssHal->setCallback(gnssCbIface);
    }
    if (!result.isOk() || !result) {
        ALOGE("SetCallback for Gnss Interface fails\n");
        return JNI_FALSE;
    }

    sp<IGnssXtraCallback> gnssXtraCbIface = new GnssXtraCallback();
    if (gnssXtraIface == nullptr) {
        ALOGE("Unable to initialize GNSS Xtra interface\n");
    } else {
        result = gnssXtraIface->setCallback(gnssXtraCbIface);
        if (!result.isOk() || !result) {
            gnssXtraIface = nullptr;
            ALOGI("SetCallback for Gnss Xtra Interface fails\n");
        }
    }

    sp<IAGnssCallback> aGnssCbIface = new AGnssCallback();
    if (agnssIface != nullptr) {
        agnssIface->setCallback(aGnssCbIface);
    } else {
        ALOGI("Unable to Initialize AGnss interface\n");
    }

    sp<IGnssGeofenceCallback> gnssGeofencingCbIface = new GnssGeofenceCallback();
    if (gnssGeofencingIface != nullptr) {
      gnssGeofencingIface->setCallback(gnssGeofencingCbIface);
    } else {
        ALOGI("Unable to initialize GNSS Geofencing interface\n");
    }

    sp<IGnssNiCallback> gnssNiCbIface = new GnssNiCallback();
    if (gnssNiIface != nullptr) {
        gnssNiIface->setCallback(gnssNiCbIface);
    } else {
        ALOGI("Unable to initialize GNSS NI interface\n");
    }

    sp<IAGnssRilCallback> aGnssRilCbIface = new AGnssRilCallback();
    if (agnssRilIface != nullptr) {
        agnssRilIface->setCallback(aGnssRilCbIface);
    } else {
        ALOGI("Unable to Initialize AGnss Ril interface\n");
    }

    return JNI_TRUE;
}

这是将jni的一些函数作为参数传递到native c 空间中去,这样在native c中如果有可用数据将通过回调的方式调用到jni中的函数。简单的看一下 location_callback的定义:

struct GnssCallback : public IGnssCallback {
    Return<void> gnssLocationCb(const GnssLocation& location) override;
    Return<void> gnssStatusCb(const IGnssCallback::GnssStatusValue status) override;
    Return<void> gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override;
    Return<void> gnssNmeaCb(int64_t timestamp, const android::hardware::hidl_string& nmea) override;
    Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override;
    Return<void> gnssAcquireWakelockCb() override;
    Return<void> gnssReleaseWakelockCb() override;
    Return<void> gnssRequestTimeCb() override;
    Return<void> gnssRequestLocationCb(const bool independentFromGnss) override;
    Return<void> gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override;

    // New in 1.1
    Return<void> gnssNameCb(const android::hardware::hidl_string& name) override;

    // TODO(b/73306084): Reconsider allocation cost vs threadsafety on these statics
    static const char* sNmeaString;
    static size_t sNmeaStringLength;
};
下一篇
举报
领券