<Android开发> Android系统开发-GNSS流程分析及实现
前言
对于安卓设备来说GNSS这个功能是必不可少的。手机、电子手表、汽车等设备都需要定位信息。GNSS涉及的有北斗、GPS、伽利略等卫星系统,GNSS设备获取到卫星信息并通过相关服务程序传送到上层应用程序。下面讲解在安卓系统中,GNSS中间部分功能,及GNSS有关的相关服务程序。
GNSS的整体流程如下:
GNSS设备 → 串口(或SPI/IIC等) → 串口(或SPI/IIC等) 驱动程序 →HAL层 → JNI 层 → java服务层 → 上层应用APP
GNSS设备:具体的GNSS芯片或模块设备;
串口(或SPI/IIC等):一般只需添加设备树节点;
串口(或SPI/IIC等) 驱动程序:一般源码都会自带这类常用的驱动程序;
HAL层 :一般模块设备厂商会提供;
JNI 层 :一般模块设备厂商会提供,与HAL层一起提供;
java服务层:安卓系统自带;
上层应用APP:用户开发;
1 GNSS 的java服务层
下面先分析java服务层部分,这部分由安卓系统自带或代码基线厂商会修改后随安卓源码一起发布。
1.1 GNSS的java服务启动入口
在SystemServer.java中添加定位服务并通过systemrunning开启;流程如:
run@SystemServer → startOtherServices() → locationF.systemRunning()
/*maincore/frameworks/base/services/java/com/android/server/SystemServer.java */
private void startOtherServices() {
…………
traceBeginAndSlog("StartLocationManagerService");
try {
location = new LocationManagerService(context);
ServiceManager.addService(Context.LOCATION_SERVICE, location);
} catch (Throwable e) {
reportWtf("starting Location Manager", e);
}
traceEnd();
…………
traceBeginAndSlog("MakeLocationServiceReady");
try {
if (locationF != null) {
locationF.systemRunning();
}
} catch (Throwable e) {
reportWtf("Notifying Location Service running", e);
}
traceEnd();
…………
从上面的代码可看出,GNSS相关的内容,主要是 申请一个位置服务管理,然后启动位置服务。这部分的调用在init.rc安卓内核启动中由介绍到,可查看相关文档。启动位置服务的详细过程将在下面部分介绍。
1.2 GNSS的位置服务启动详细过程
1.2.1 initializeLocked()
通过函数的调用流程可知,systemRunning() → initializeLocked() ;函数 initializeLocked() 的具体内容如下:
/*maincore/frameworks/base/services/core/java/com/android/server/LocationManagerService.java */
public void systemRunning() {
synchronized (mLock) {
initializeLocked();
}
}
@GuardedBy("mLock")
private void initializeLocked() {
mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
mPackageManager = mContext.getPackageManager();
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mLocationFudger = new LocationFudger(mContext, mHandler);
mBlacklist = new LocationBlacklist(mContext, mHandler);
mBlacklist.init();
mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
// prepare providers
// 准备提供者
initializeProvidersLocked();
// add listeners
// 添加监听器
mAppOps.startWatchingMode(
AppOpsManager.OP_COARSE_LOCATION,
null,
AppOpsManager.WATCH_FOREGROUND_CHANGES,
new AppOpsManager.OnOpChangedInternalListener() {
public void onOpChanged(int op, String packageName) {
// onOpChanged invoked on ui thread, move to our thread to reduce risk of
// blocking ui thread
// onOpChanged 在 ui 线程上调用,移动到我们的线程以减少阻塞 ui 线程的风险
mHandler.post(() -> {
synchronized (mLock) {
onAppOpChangedLocked();
}
});
}
});
mPackageManager.addOnPermissionsChangeListener(
uid -> {
// listener invoked on ui thread, move to our thread to reduce risk of blocking
// ui thread
// 在 ui 线程上调用的监听器,移动到我们的线程以减少阻塞 ui 线程的风险
mHandler.post(() -> {
synchronized (mLock) {
onPermissionsChangedLocked();
}
});
});
mActivityManager.addOnUidImportanceListener(
(uid, importance) -> {
// listener invoked on ui thread, move to our thread to reduce risk of blocking
// ui thread
// 在 ui 线程上调用的监听器,移动到我们的线程以减少阻塞 ui 线程的风险
mHandler.post(() -> {
synchronized (mLock) {
onUidImportanceChangedLocked(uid, importance);
}
});
},
FOREGROUND_IMPORTANCE_CUTOFF);
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.LOCATION_MODE), true,
new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
synchronized (mLock) {
onLocationModeChangedLocked(true);
}
}
}, UserHandle.USER_ALL);
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
synchronized (mLock) {
onProviderAllowedChangedLocked();
}
}
}, UserHandle.USER_ALL);
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
true,
new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
synchronized (mLock) {
onBackgroundThrottleIntervalChangedLocked();
}
}
}, UserHandle.USER_ALL);
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(
Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
true,
new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
synchronized (mLock) {
onBackgroundThrottleWhitelistChangedLocked();
}
}
}, UserHandle.USER_ALL);
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(
Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST),
true,
new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
synchronized (mLock) {
onIgnoreSettingsWhitelistChangedLocked();
}
}
}, UserHandle.USER_ALL);
PowerManagerInternal localPowerManager =
LocalServices.getService(PowerManagerInternal.class);
localPowerManager.registerLowPowerModeObserver(ServiceType.LOCATION,
state -> {
// listener invoked on ui thread, move to our thread to reduce risk of blocking
// ui thread
// 在 ui 线程上调用的监听器,移动到我们的线程以减少阻塞 ui 线程的风险
mHandler.post(() -> {
synchronized (mLock) {
onBatterySaverModeChangedLocked(state.locationMode);
}
});
});
new PackageMonitor() {
@Override
public void onPackageDisappeared(String packageName, int reason) {
synchronized (mLock) {
LocationManagerService.this.onPackageDisappearedLocked(packageName);
}
}
}.register(mContext, mHandler.getLooper(), true);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
mContext.registerReceiverAsUser(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action == null) {
return;
}
synchronized (mLock) {
switch (action) {
case Intent.ACTION_USER_SWITCHED:
onUserChangedLocked(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
break;
case Intent.ACTION_MANAGED_PROFILE_ADDED:
case Intent.ACTION_MANAGED_PROFILE_REMOVED:
onUserProfilesChangedLocked();
break;
case Intent.ACTION_SCREEN_ON:
case Intent.ACTION_SCREEN_OFF:
onScreenStateChangedLocked();
break;
}
}
}
}, UserHandle.ALL, intentFilter, null, mHandler);
// switching the user from null to system here performs the bulk of the initialization work.
// the user being changed will cause a reload of all user specific settings, which causes
// provider initialization, and propagates changes until a steady state is reached
// 在这里将用户从 null 切换到 system 执行大部分初始化工作。
// 被更改的用户将导致重新加载所有用户特定的设置,这会导致提供程序初始化,并传播更改直到达到稳定状态
mCurrentUserId = UserHandle.USER_NULL;
onUserChangedLocked(ActivityManager.getCurrentUser());
// initialize in-memory settings values
// 初始化内存中的设置值
onBackgroundThrottleWhitelistChangedLocked();
onIgnoreSettingsWhitelistChangedLocked();
onBatterySaverModeChangedLocked(mPowerManager.getLocationPowerSaveMode());
}
函数initializeLocked()主要是初始化相关内容,其中调用initializeProvidersLocked()加载gnssProvider和bind相关provider。
1.1.2 initializeProvidersLocked()
接着看看函数initializeProvidersLocked()的内容,如下:
/* frameworks/base/services/core/java/com/android/server/LocationManagerService.java */
@