一、Settings
打开GPS的方法往数据库里面写值,然后framework层读取值再做相应处理。
packages/apps/Settings/src/com/android/settings/location/LocationSwitchBarController.java
public void onSwitchChanged(Switch switchView, boolean isChecked) {
mLocationEnabler.setLocationEnabled(isChecked);
}
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
底层GNSS服务启动
IGnss* HIDL_FETCH_IGnss(const char* /* hal */) {
hw_module_t* module;
IGnss* iface = nullptr;
int err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
if (err == 0) {
hw_device_t* device;
err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
if (err == 0) {
iface = new Gnss(reinterpret_cast<gps_device_t*>(device));
} else {
ALOGE("gnssDevice open %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
}
} else {
ALOGE("gnss hw_get_module %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
}
return iface;
}
mGnssIface底层modem 厂商驱动 interface
Gnss::Gnss(gps_device_t* gnssDevice) :
mDeathRecipient(new GnssHidlDeathRecipient(this)) {
/* Error out if an instance of the interface already exists. */
LOG_ALWAYS_FATAL_IF(sInterfaceExists);
sInterfaceExists = true;
if (gnssDevice == nullptr) {
ALOGE("%s: Invalid device_t handle", __func__);
return;
}
mGnssIface = gnssDevice->get_gps_interface(gnssDevice);
}
Gnss::setCallback gnssHal->setCallback(gnssCbIface);
// Methods from ::android::hardware::gnss::V1_0::IGnss follow.
Return<bool> Gnss::setCallback(const sp<IGnssCallback>& callback) {
if (mGnssIface == nullptr) {
ALOGE("%s: Gnss interface is unavailable", __func__);
return false;
}
if (callback == nullptr) {
ALOGE("%s: Null callback ignored", __func__);
return false;
}
if (sGnssCbIface != NULL) {
ALOGW("%s called more than once. Unexpected unless test.", __func__);
sGnssCbIface->unlinkToDeath(mDeathRecipient);
}
sGnssCbIface = callback;
callback->linkToDeath(mDeathRecipient, 0 /*cookie*/);
// If this was received in the past, send it up again to refresh caller.
// mGnssIface will override after init() is called below, if needed
// (though it's unlikely the gps.h capabilities or system info will change.)
if (sCapabilitiesCached != 0) {
setCapabilitiesCb(sCapabilitiesCached);
}
if (sYearOfHwCached != 0) {
LegacyGnssSystemInfo info;
info.year_of_hw = sYearOfHwCached;
setSystemInfoCb(&info);
}
return (mGnssIface->init(&sGnssCb) == 0);
}
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;
}
/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;
};
-
一、Settings
打开GPS的方法往数据库里面写值,然后framework层读取值再做相应处理。
packages/apps/Settings/src/com/android/settings/location/LocationSwitchBarController.java
public void onSwitchChanged(Switch switchView, boolean isChecked) { mLocationEnabler.setLocationEnabled(isChecked); }
- 1
这是将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;
};