Android GNSS 模块分析(二)FrameWork 层

大家好,本章节是介绍 Android GNSS Framework 层服务 LocationManagerService 的相关流程。此篇为学习记录随笔,文中若有错误,还请大家不吝告知,指正修改,小弟先行告谢!!!

1、前言        

        紧接着上一篇分析 Android GNSS 应用层分析(一),本篇将会分析 Framework 层 Location 服务的流程。Android 中 Location 服务端文件为 LocationManagerService.java。在开机时,系统会启动并初始化 Location 服务,并且注册到 ServiceManager 中去给外界提供服务,API 中的 LocationManager 再与 Location 服务建立连接,向外界提供服务。Location 服务端对下呢,通过 JNI 的方式,与底层的 GNSS 服务交互,建立与底层的通信。本篇将从两个方面去介绍下 Framework GNSS 服务:

        * Location 服务构造和服务注册

        * Location 准备工作初始化

        * Location 接收上层请求序列流转

2、Location 服务启动序列图

Android GNSS 模块分析(二)FrameWork 层_第1张图片

         先简单概述下 Location 服务开启的整体过程。系统在开机启动的时候,在 SystemServer 阶段,会在 startOtherServices() 阶段启动 Location 服务;执行 LocationManagerService 构造方法创建 Location 服务对象;紧接着系统在启动到 PHASE_THIRD_PARTY_APPS_CAN_START 阶段时,SystemServer 会调用 Location 服务的 systemRunning() 函数去完成 Location 服务的功能初始化工作;这个阶段比较重要的是 Location 服务初始化 LocationProvider,为后面提供位置服务做准备;GnssLocationProvider 是 Android 提供的 GPS 芯片位置服务,通过静态代码块去建立和底层的通信通道,在构造方法中再调用一系列 native 函数和底层通信。最后 GnssLocationProvider 初始化完毕后通知 Location 服务 Provider 已经准备完毕。这些就是 Location 服务在启动过程中的大概过程 ,下面我们分步走下流程。

2.1、 Location 服务的启动和注册

2.1.1 SystemServer.java

        系统在开机启动的时候,在 SystemServer 阶段,会在 startOtherServices() 阶段启动 Location 服务。

Android GNSS 模块分析(二)FrameWork 层_第2张图片

(android/frameworks/base/services/java/com/android/server/SystemServer.java)

        其中,构造了 LocationManagerService 对象,并且将此对象注册到了 ServiceManager 中。SystemServer 是 Android 启动过程中比较重要的阶段,Android 的许多服务的创建注册就是在这个阶段完成,启动中 init 进程通过解析 zygote rc文件,启动了 zygote 进程,开启了Android 中的 Java 之路,继而 zygote 进程又 fork 出 SystemServer 进程,去完成系统服务的创建初始化工作,像系统重要服务 AMS、PMS、WMS等都是这个阶段完成的,最后 SystemServer 启动 桌面应用 Launcher,把 Android 的桌面显示出来。对于 Android 启动流程 bootloader -> kernel -> init -> zygote -> systemserver -> launcher 这个过程如果不清楚的话,建议还是先了解下。

        关于 ServiceManager。众所周知,Android 是基于 Linux 的。Linux 中的进程间通信,像是共享内存、 Socket、管道等在 Android 上都或多或少存在某些场景存在问题,于是 Android 特有进程间通信 Binder 登场了。其中 ServiceManager 类就是 Binder 机制中专门用来注册和管理服务的类。当应用程序想要使用服务时,需要通过获取服务的代理来调用服务,这样客户端进程与服务进程分别处于两个进程中,实现进程间通信。Binder Driver 时 Binder 机制的核心部分,完成底层进程间通讯的工作。这部分内容有兴趣可以去详细了解。

2.1.2 LocationManagerService 构造函数

Android GNSS 模块分析(二)FrameWork 层_第3张图片

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

        可以发现在 Location 服务的构造函数中,没有完成过多的工作:

        * 主要是获取 Handler 对象,用于线程间通信;

        * mLocationUsageLogger 是跟 LocationManagerService 同目录下,这个类的功能是提供两个同名重载方法 logLocationApiUsage(),作用是打印日志,并且使用 StatusLog.write() 函数做了记录;

        * 相对重要的是获取 PackageManagerInternal 对象,配置 LocationPackageProvider。com.android.internal 这个包是根据 frameworks/base/core/res 路径下的资源文件打包出来的。

Android GNSS 模块分析(二)FrameWork 层_第4张图片

 (frameworks/base/core/res/res/values/config.xml)

        传入的 config_locationProviderPackageNames 这个字符串的定义是 com.android.location.fused,检索代码 com.android.location.fused 实际上是一个 APK,其中包含一个 Service 组件,名为 com.android.location.fused.FusedLocationService。代码路径在 frameworks/base/packages/FusedLocation 下。

        setLocation*PackageProvider() 函数传入的是 PackageProvider 对象。先来看下 PackageProvider 是什么。

Android GNSS 模块分析(二)FrameWork 层_第5张图片

 (frameworks/base/core/java/android/content/pm/PackageManagerInternal.java)

        PackageProvider 定义的一个接口,只有一个方法 getPackages(userId),那么在 LocationManagerService 的构造函数中,传入的参数就是构造了一个 PackageProvider 对象,而 getPackages() 返回的 String 就是 com.android.location.fused。再看 setLocationPackagesProvider() 函数,此函数的函数流转会到 DefaultPermissionGrantPolicy.java 中去,估计是跟 运行时权限 或者 权限检查 相关的工作。

Android GNSS 模块分析(二)FrameWork 层_第6张图片

(setLocationPackageProvider序列图)

        从 LocationManagerService 中的 setLocationPackagesProvider() 函数传入的 PackageProvider 对象最终是传入到 DefaultPermissionGrantPolicy 中去,接收的参数是 mLocationPackagesProvider,是 private 私有变量,内部只提供给一个方法局部变量 locationPackagesProvider 赋值,在 grantDefaultSystemHandlerPermissions() 方法中局部使用,而这个方法,在开机时 PMS 初始化的过程中就会调用,作用就是给系统默认的一些包授予特定的运行时权限,最终对于 Location 而言,就是给 com.android.location.fused 应用赋予一些 location 特定的权限。grantDefaultSystemHandlerPermissions() 中关于 location 默认应用赋予权限的代码,具体权限如下:

Android GNSS 模块分析(二)FrameWork 层_第7张图片

(frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java)

2.1.3 Location 服务的注册

        这里提到的注册主要有两个注册:第一个注册是在 SystemServer 中将 location 服务注册到 ServiceManager中去;第二个注册是在 SystemServiceRegistry 中服务的注册。

2.1.3.1 注册到 ServiceManager

        这部分就是上面代码中所提到的 ServiceManager.add(),将 Location 服务注册到 Binder 中去,客户端可以通过 Binder 拿到此服务的代理。

2.1.3.2 注册到 SystemServiceRegistry

        SystemServiceRegistry 类主要是用来注册、缓存、获取系统服务的。SystemServiceRegistry 加载到内存中时,代码中的静态代码块就会执行,系统服务的注册就是在静态代码块中完成的。

Android GNSS 模块分析(二)FrameWork 层_第8张图片

 (frameworks/base/core/java/android/app/SystemServiceRegistry.java)

        在静态代码块中,就是这里将 Context.LOCATION_SERVICE 将 LocationManager 和 LocationManagerService 绑定起来,API 接口 LocationManager 中就是通过这里的注册拿到 LocationManagerService 服务的。

        系统服务在静态代码块中注册后,对 Service 缓存的数组时记录在 ContextImpl 中的,不同的 ContextImpl 对象缓存数组不同。

        从整体来看,SystemServiceRegistry 的构造函数是私有的,并且构造函数也没有在内部调用,说明是不能在类外创建对象,SystemServiceRegistry 的其他方法和字段基本上都是静态的,那么基本上可以确定 SystemServiceRegistry 是用作 Util 类来使用的。不过 SystemServiceRegistry 是什么时候导入内存的,这一点大家有兴趣可以找一下,预估应该是启动较晚点的阶段。

2.2 、Location 服务初始化流程

2.2.1 SystemServer.systemRunning()

        SystemServer 阶段启动 Location 服务的第一部分就结束了,那么可以发现,这个阶段实际没有完成什么准备工作,仅是创建了服务,并且添加到 ServiceManager 中去。对于 Location 服务所需要的变量、结构等并没有做初始化准备。实际上这些工作被放到了 initializeLocked() 初始化中去完成。

        在 SystemServer 启动到 PHASE_THIRD_PARTY_APPS_CAN_START 阶段时,SystemServer 会调用 Location 服务的 systemRunning() 函数去完成 Location 服务的功能初始化工作。

Android GNSS 模块分析(二)FrameWork 层_第9张图片

 (android/frameworks/base/services/java/com/android/server/SystemServer.java)

        进入 LocationManagerService 中,systemRunning() 函数中实际上就是调用了 initializeLocked() 函数去完成初始化工作。

Android GNSS 模块分析(二)FrameWork 层_第10张图片

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

 2.2.2 LocationManagerService.initializedLocked()

private void initializeLocked() {
    // 初始化第一阶段 服务变量的获取
    mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); // 应用权限管理服务,在后续用于注册模式监听
    mPackageManager = mContext.getPackageManager();  // 包管理服务,在后续用于注册权限改动监听
    mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);  // 电源管理服务,在后续初始化值onBatterySaverModeChangedLocked()中用作参数
    mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);  // Activity 服务,在后续用于注册监听
    mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);  // 用户管理服务,在后续有关用户的操作

    // 下面的初始化,是在 location 目录内部
    mLocationFudger = new LocationFudger(mContext, mHandler);  // LocationFudger功能:可以创建一个粗略的location位置
    mBlacklist = new LocationBlacklist(mContext, mHandler);  // 创建应用黑名单,应用被拉入黑名单后,仍然可以正常调用接口,不过没有数据返回
    mBlacklist.init();
    mGeofenceManager = new GeofenceManager(mContext, mBlacklist);  // Geofence 管理,地理围栏,当接近某个位置/离开某个位置时,可以触发某些动作,警告等

    // prepare providers
    // 完成 LocationProvider 初始化的相关工作
    initializeProvidersLocked();

    // add listeners
    // 注册监听
    
    // 监听 Op 变化 OP_COARSE_LOCATION 获取粗略位置权限,检测到有改变后,调用回调。
    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
                    mHandler.post(() -> {
                        synchronized (mLock) {
                            onAppOpChangedLocked();
                        }
                    });
                }
            });
    // 
    mPackageManager.addOnPermissionsChangeListener(
            uid -> {
                // listener invoked on ui thread, move to our thread to reduce risk of blocking
                // ui thread
                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
                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
                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
    mCurrentUserId = UserHandle.USER_NULL;
    onUserChangedLocked(ActivityManager.getCurrentUser());

    // initialize in-memory settings values
    onBackgroundThrottleWhitelistChangedLocked();
    onIgnoreSettingsWhitelistChangedLocked();
    onBatterySaverModeChangedLocked(mPowerManager.getLocationPowerSaveMode());
}

        在 initializedLock() 函数内部,主要做了三件事。

        第一件事:调用 initializeProvidersLocked() 去做 LocationProvider 相关的初始化工作,在整个 GNSS 的架构中,LocationProvider 是一个非常重要的部分,这部分内容是连接底层/第三方,获取数据的关键。整个 GNSS 的数据是怎么提供的,怎么拿到数据的,以什么形式拿到的都要去分析 LocationProvider。

        第二件事:注册了一系列的监听,这部分监听大多关于权限相关、以及针对某些配置的内容检测,传入监听,有改动时回调通知。

        第三件事:注册了一个动态广播,以及调用函数去完成值、状态的预设。

2.2.3 LocationManagerService.initializeProvidersLocked()

private void initializeProvidersLocked() {
        // create a passive location provider, which is always enabled
		// 先创建 passive 模式的 LocationProvider。这个 passive 的 LocationProvider 的所提供的数据并不是来源于系统的 GPS 数据,而是其他程序提供的。
        LocationProvider passiveProviderManager = new LocationProvider(PASSIVE_PROVIDER);
		// 把 passiveProviderManager 加入到 mProviders 中去,mProviders 记录的时所有在使用的 LocationProvider 
		// private final ArrayList mProviders = new ArrayList<>();
        addProviderLocked(passiveProviderManager);
		// 创建 PassiveProvider 提供 Passive 位置信息
        mPassiveProvider = new PassiveProvider(mContext, passiveProviderManager);
		// 将 passiveProviderManager 与 PassiveProvider 关联起来
        passiveProviderManager.attachLocked(mPassiveProvider);
	// 这里的静态方法调用,实际会进行 GnssLocationProvider 的类加载过程,也包括在静态代码块中 JNI 的注册,以及和底层连接
	// 这里的 isSupported() 执行前会加载静态代码块中的 JNI 注册。class_init_native()主要完成了 gnssHal 服务的初始化以及 JNI 方法的连接注册
	// gnssHal 服务在源码中有几个版本的实现,在这里是按顺序拿取的:gnssHal_V2_0、gnssHal_V1_1、gnssHal_V1_1。
    if (GnssLocationProvider.isSupported()) {   // isSupported() 返回的就是 gnssHal 服务对象是否有初始化,成功初始化代表底层支持 Gnss 服务。
        // 创建 GPS 模式的 LocationProvider。
        LocationProvider gnssProviderManager = new LocationProvider(GPS_PROVIDER, true);
        mRealProviders.add(gnssProviderManager);
        addProviderLocked(gnssProviderManager);

		// 创建 gnssProvider 提供 gps 数据
        GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext,
                gnssProviderManager,
                mHandler.getLooper());
		// 将 gnssProviderManager 与 gnssProvider 关联起来
        gnssProviderManager.attachLocked(gnssProvider);

		// 获取 GNSS 系统信息回调对象,可以获取 mHardwareYea、mHardwareModelName
        mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
		
        mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
		// 获取 GNSS Metrics 回调对象,可以获取 GNSS String数据
		mGnssMetricsProvider = gnssProvider.getGnssMetricsProvider();
		// 获取 GNSS 功能信息回调对象,可以获取 GNSS 芯片组所支持的功能,这些功能与 API 接口中的 GnssCapabilities.java 中有对应的定义。
        mGnssCapabilitiesProvider = gnssProvider.getGnssCapabilitiesProvider();
		/*
		 * mGnssStatusProvider 回调对象用于提供 GnssStatus 的数据,外部提供 IGnssStatusListener 的实现,来监听 GNSS 卫星状态的变化
		 * GnssStatusListenerHelper 是继承 RemoteListenerHelper 工具类实现的,其他类似的实现还有 GnssMeasurementsProvider、GnssNavigationMessageProvider
		 * 支持的功能有
		 *			void onGnssStarted();
		 *			void onGnssStopped();
		 *			void onFirstFix(int ttff);
		 *			void onSvStatusChanged(int svCount, in int[] svidWithFlags, in float[] cn0s, in float[] elevations, in float[] azimuths, in float[] carrierFreqs);
		 *			void onNmeaReceived(long timestamp, String nmea);
		 */	
        mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
		
		// INetInitiatedListener 对象,是 INetInitiatedListener.Stub() 的实现,定义在 API 中的 INetInitiatedListener.aidl 文件中
		// 包含一个方法 sendNiResponse() 主要是判断的 GnssHal 是否支持 Network 通信
        mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
		// 提供 GPS 测量数据的实现,是 IGnssMeasurementsListener 监听数据的提供类。提供的功能可见 IGnssMeasurement.aidl
		// onGnssMeasurementsReceived()、onStatusChanged()
        mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
		
        mGnssMeasurementCorrectionsProvider =
                gnssProvider.getGnssMeasurementCorrectionsProvider();
		// IGnssNavigationMessageListener 的监听提供类,支持的功能见 IGnssNavigationMessageListener.aidl
		// onGnssNavigationMessageReceived()、onStatusChanged()
        mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider();
		
        mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
    }

    /*
    Load package name(s) containing location provider support.
    These packages can contain services implementing location providers:
    Geocoder Provider, Network Location Provider, and
    Fused Location Provider. They will each be searched for
    service components implementing these providers.
    The location framework also has support for installation
    of new location providers at run-time. The new package does not
    have to be explicitly listed here, however it must have a signature
    that matches the signature of at least one package on this list.
    */
    Resources resources = mContext.getResources();
    String[] pkgs = resources.getStringArray(  // com.android.location.fused 应用
            com.android.internal.R.array.config_locationProviderPackageNames);
    if (D) {
        Log.d(TAG, "certificates for location providers pulled from: " +
                Arrays.toString(pkgs));
    }

    ensureFallbackFusedProviderPresentLocked(pkgs);
	
	/*
	 *	下面的 Provider 的创建基本上都是用类似的方法创建的,使用 LocationProviderProxy 的方式创建。
	*/

    // 绑定网络定位提供 networkProviderManager
    LocationProvider networkProviderManager = new LocationProvider(NETWORK_PROVIDER, true);
	// 创建一个新的 LocationProviderProxy 对象,并且绑定到最适用的服务
    LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
            mContext,
            networkProviderManager,
            NETWORK_LOCATION_SERVICE_ACTION,
            com.android.internal.R.bool.config_enableNetworkLocationOverlay,
            com.android.internal.R.string.config_networkLocationProviderPackageName,
            com.android.internal.R.array.config_locationProviderPackageNames);
    if (networkProvider != null) {
        mRealProviders.add(networkProviderManager);
        addProviderLocked(networkProviderManager);
        networkProviderManager.attachLocked(networkProvider);
    } else {
        Slog.w(TAG, "no network location provider found");
    }

    // bind to fused provider
    LocationProvider fusedProviderManager = new LocationProvider(FUSED_PROVIDER);
    LocationProviderProxy fusedProvider = LocationProviderProxy.createAndBind(
            mContext,
            fusedProviderManager,
            FUSED_LOCATION_SERVICE_ACTION,
            com.android.internal.R.bool.config_enableFusedLocationOverlay,
            com.android.internal.R.string.config_fusedLocationProviderPackageName,
            com.android.internal.R.array.config_locationProviderPackageNames);
    if (fusedProvider != null) {
        mRealProviders.add(fusedProviderManager);
        addProviderLocked(fusedProviderManager);
        fusedProviderManager.attachLocked(fusedProvider);
    } else {
        Slog.e(TAG, "no fused location provider found",
                new IllegalStateException("Location service needs a fused location provider"));
    }

    // bind to geocoder provider
    mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
            com.android.internal.R.bool.config_enableGeocoderOverlay,
            com.android.internal.R.string.config_geocoderProviderPackageName,
            com.android.internal.R.array.config_locationProviderPackageNames);
    if (mGeocodeProvider == null) {
        Slog.e(TAG, "no geocoder provider found");
    }

    // bind to geofence provider
    GeofenceProxy provider = GeofenceProxy.createAndBind(
            mContext, com.android.internal.R.bool.config_enableGeofenceOverlay,
            com.android.internal.R.string.config_geofenceProviderPackageName,
            com.android.internal.R.array.config_locationProviderPackageNames,
            mGpsGeofenceProxy,
            null);
    if (provider == null) {
        Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
    }

    // bind to hardware activity recognition
    boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
    ActivityRecognitionHardware activityRecognitionHardware = null;
    if (activityRecognitionHardwareIsSupported) {
        activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
    } else {
        Slog.d(TAG, "Hardware Activity-Recognition not supported.");
    }
    ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
            mContext,
            activityRecognitionHardwareIsSupported,
            activityRecognitionHardware,
            com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
            com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
            com.android.internal.R.array.config_locationProviderPackageNames);
    if (proxy == null) {
        Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
    }
}

        此方法主要就是初始化 Provider,初始化的 Provider 有 passiveProvider、GnssLocationProvider、networkProvider、fusedProvider、GeocoderProxy、GeofenceProxy。

        首先创建了一个 PassiveProvider,并加入到可用的 provider 数组里面缓存。

        其次创建了比较重要的 GnssLocationProvider。GnssLocationProvider 使用的是系统 GPS 模块所提供的定位服务。

        然后创建 networkProvider 和 fusedProvider,这两种创建方式是通过 LocationProviderProxy 实现的,LocationProviderProxy 是代理,第三方 NLP 去实现 LocationProviderProxy 的具体功能。

        后面又加入了融合定位的 Provider 和 GeocoderProvider,这两个和 NLP 的代理过程类似。实现方式是提供了类似与 LocationProviderProxy 的实现方式,使用独立的类去实现。

2.2.4 GnssLocationProvider 的实现

        GnssLocationProvider 初始化的入口是从 LocationManagerService 中初始化 Provider 开始的。调用 GnssLocationProvider.isSupported() 去加载 GnssLocationProvider 类,此时会加载 GnssLocationProvider 中静态代码块的内容,去做 JNI 相关初始化的工作。

Android GNSS 模块分析(二)FrameWork 层_第11张图片

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

        虚拟机加载 GnssLocationProvider 类,会先执行静态代码块内容。

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

        这里会调用到 JNI 中

Android GNSS 模块分析(二)FrameWork 层_第12张图片

(android/frameworks/base/services/core/jni/com_android_server_location_GnssLocationProvider.cpp)

        这里完成两件事:调用 android_location_GnssLocationProvider_set_gps_service_handle() 去连接 GnssHal 服务、缓存配对方法 ID 和 类 ID。

Android GNSS 模块分析(二)FrameWork 层_第13张图片

android_location_GnssLocationProvider_set_gps_service_handle() 

        在 JNI 连接 GnssHal 层服务时,会做三次检查,先获取2.0版本的服务;如果没有实现,再获取1.1版本的服务;如果仍然没有实现,就获取1.0版本的服务。HAL 层服务提供的实现在源码的 android/hardware/interfaces/gnss 目录下

         在 Android Q 版本的代码中,具体实现是在 1.0 中,1.1 以及 2.0 是在 1.0 的接口基础上进行了扩展,但是接口的实现并没有完成。

GnssLocationProvider.isSupported()

         那么判断是否支持 GNSS 服务的话,实际上就是判断 gnssHal 对象是否有初始化,是否有获取到底层 GnssHal 服务的对象。

        GnssLocationProvider 的构造方法传入了三个参数

        * Context 是 LocationManagerService 中的 mContext

        * LocationProviderManager 是在 LocationManagerService 传入的 LocationProvider 对象,主要的作用就是调用到 LocationManagerService 中的 LocationProvider 的 onReportLocation() 函数上报位置信息;最终是调用到 LocationProviderManager.LocationProvider 中去,中间从 AbstractLocationProvider 过渡一次,再由 AbstractLocationProvider 中保存的 LocationProvider 实现类,调用到 LocationManagerService 中去。

        * Looper 是 LocationManagerService 中的 looper 对象。

        构造方法中内容比较多,这里先关注 sendMessage(INITIALIZE_HANDLER, 0, null) 这里的通信,其他创建的类对象有很多,先来看下这里用 Handler 通信,发送 INITIALIZE_HANDLER,在接收端调用 handleInitialize() 去处理。

        handleInitialize()

        Provider 初始化的过程完成了如下工作:

        A、setupNativeGnssService(true)。调用 native_init_once() 去进行 Native 层的初始化,此方法只有在系统重启,或者 GNSS 服务挂了之后,才会调用;调用 native_init() 去进行底层回调对象 callback 的注册,每次 GPS 服务挂了之后,需要重新调用;如果 native_init() 底层回调注册成功,调用 native_cleanup() 去 cleanup gnssHal;

        B、reloadGpsProperties()。加载默认的GPS配置,这个配置可能跟SIM的变化而改变;这个过程是 从运行商配置文件加载 GNSS 属性,然后从 gps 调试配置文件加载属性。这部分实现在 GnssConfiguration 中,提供的 reloadGpsProperties() 是功能接口。

        C、mNetworkConnectivityHandler.registerNetworkCallbacks()。前面在初始化的过程中,创建了 NetworkConnectivityHandler 对象,主要是监听网络连接的状态。

        D、locManager.requestLocationUpdates。开启 PASSIVE_PROVIDER 的更新,调用方法获取 PASSIVE_PROVIDER 的 Provider 信息。

        E、updateEnabled()。实现在 handleEnable() 中。这里也有跟 JNI / 底层进行通信。去完成底层回调的注册等准备工作。

        到这里基本上走完了 LocationManagerService 服务初始化的大致流程。初始化的过程是复杂的,仍有很多代码细节需要去分析。仍有很多模块功能交互需要分析。

2.3 Location 接收上层请求序列流转

2.3.1 requestLocationUpdates序列图

Android GNSS 模块分析(二)FrameWork 层_第14张图片

 (requestLocationUpdates序列图)

        先来一张 requestLocationUpdates() 上层发起位置请求函数的序列图。服务端接收到应用端传过来的位置请求,会封装 WorkSource 和 LocationRequest;并且将 LocationListener 保存到 Receiver 包装类中,存在 HashMap mReceiver 中。 然后将请求通过 JNI,下发到底层。

2.3.2 底层回调Location位置信息序列图

Android GNSS 模块分析(二)FrameWork 层_第15张图片

(底层回调Location位置信息序列图)

        Hal 层会通过 JNI 注册的回调,将 Location 信息回调到 JNI 层,然后上层与 JNI 绑定的函数,回调到上层中。上层的绑定函数是 reportLocation() 函数。紧接着 Location 数据会被传入到 LocationManagerService 中。通过之前保存的 mReceiver 封装类,将应用所需要的位置信息通过内部的 ILocationListener 对象,通知到应用。

总结:以上便是从三个流程去理解 Android GNSS Framework 服务,当然代码中仍然还有很多功能细节没有分析到位,谨以学习记录开篇,后续持续修正。如果大家对文中内容不解处,或者对分享内容有异议,烦请告知作者,必当有则改之,无则加勉。在此,小弟先行告谢!

联系作者:

上一篇:Android GNSS 模块分析(一)整体介绍 - App

下一篇:Android GNSS 模块分析(三) JNI 层

你可能感兴趣的:(GNSS,android)