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 changesmContext.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;};
更多相关文章
- 浅谈Java中Collections.sort对List排序的两种方法
- 箭头函数的基础使用
- Python技巧匿名函数、回调函数和高阶函数
- Python list sort方法的具体使用
- python list.sort()根据多个关键字排序的方法实现
- Android(安卓)获取网络状态及调用网络配置界面(转帖)
- Android上调用google map api v2
- Android(安卓)UI系列:关于按钮点击事件
- Android文件浏览器的开发