浅析Android 11 Gnss定位流程

3,715 阅读15分钟

之前在Android11平台上移植了GNSS功能,并把移植工作整理了一个文档,可参考《高通Android 11平台上移植GNSS》,现在从源码的角度来分析一下GNSS实现定位的整体流程,本文基于Android 11。

架构设计图

gnss框架.png

APP层

我们在做app开发定位功能时,除了使用高德/百度定位,通常还使用原生的LocationManager来获取定位数据,核心代码如下:

    //代码5
	private LocationListener locationListener = new LocationListener() {
        @Override
        public void onLocationChanged(@NonNull Location location) {
            //打印定位数据
            Log.d(TAG, "onLocationChanged: " + location.toString());
        }
    };

	public void startLocation(View view) {
        //动态授权
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(this, "请先授予定位权限", Toast.LENGTH_SHORT).show();
            return;
        }
        //判断GPS是否打开
        boolean isOpen = checkGPSIsOpen(this);
        if (!isOpen) {
            Toast.makeText(this, "请先打开GPS", Toast.LENGTH_SHORT).show();
            goToGpsSetting(this);
            return;
        }
        //获取定位服务,请求定位数据
        LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0.01f, locationListener);
    }

最后得到如下定位数据:

gps定位数据.png

AIDL层

上述代码主要是通过locationManager.requestLocationUpdates()来获取定位数据,看看此方法的实现

	@UnsupportedAppUsage
    private final ILocationManager mService;

	@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
    public void requestLocationUpdates(@NonNull String provider, long minTimeMs, float minDistanceM,
            @NonNull LocationListener listener, @Nullable Looper looper) {
        Preconditions.checkArgument(provider != null, "invalid null provider");
        Preconditions.checkArgument(listener != null, "invalid null listener");

        LocationRequest request = LocationRequest.createFromDeprecatedProvider(
                provider, minTimeMs, minDistanceM, false);
        requestLocationUpdates(request, listener, looper);
    }

    @SystemApi
    @TestApi
    @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
    public void requestLocationUpdates(
            @Nullable LocationRequest locationRequest,
            @NonNull LocationListener listener,
            @Nullable Looper looper) {
        Handler handler = looper == null ? new Handler() : new Handler(looper);
        requestLocationUpdates(locationRequest, new HandlerExecutor(handler), listener);
    }

    @SystemApi
    @TestApi
    @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
    public void requestLocationUpdates(
            @Nullable LocationRequest locationRequest,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull LocationListener listener) {
        synchronized (mListeners) {
            LocationListenerTransport transport = mListeners.get(listener);
            if (transport != null) {
                transport.unregister();
            } else {
                transport = new LocationListenerTransport(listener);
                mListeners.put(listener, transport);
            }
            transport.register(executor);

            boolean registered = false;
            try {
                //AIDL调用LocationManagerService的requestLocationUpdates()方法
                mService.requestLocationUpdates(locationRequest, transport, null,
                        mContext.getPackageName(), mContext.getAttributionTag(),
                        transport.getListenerId());
                registered = true;
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            } finally {
                if (!registered) {
                    // allow gc after exception
                    transport.unregister();
                    mListeners.remove(listener);
                }
            }
        }
    }

可以看到最终通过mService调用了远程LocationManagerService里面的方法,mService是一个ILocationManager.aidl接口,该接口的定义如下

/**
 * System private API for talking with the location service.
 *
 * @hide
 */
interface ILocationManager
{
    Location getLastLocation(in LocationRequest request, String packageName, String featureId);
    @nullable ICancellationSignal getCurrentLocation(in LocationRequest request,
            in ILocationListener listener, String packageName, String featureId,
            String listenerId);

    void requestLocationUpdates(in LocationRequest request, in ILocationListener listener,
            in PendingIntent intent, String packageName, String featureId, String listenerId);
    void removeUpdates(in ILocationListener listener, in PendingIntent intent);

    void requestGeofence(in LocationRequest request, in Geofence geofence,
            in PendingIntent intent, String packageName, String featureId);
    void removeGeofence(in Geofence fence, in PendingIntent intent, String packageName);

    boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName,
            String featureId);
    void unregisterGnssStatusCallback(IGnssStatusListener callback);

    boolean geocoderIsPresent();
    String getFromLocation(double latitude, double longitude, int maxResults,
        in GeocoderParams params, out List<Address> addrs);
    String getFromLocationName(String locationName,
        double lowerLeftLatitude, double lowerLeftLongitude,
        double upperRightLatitude, double upperRightLongitude, int maxResults,
        in GeocoderParams params, out List<Address> addrs);

    boolean addGnssMeasurementsListener(in GnssRequest request,
            in IGnssMeasurementsListener listener,
            String packageName, String featureId);
    void injectGnssMeasurementCorrections(in GnssMeasurementCorrections corrections,
            in String packageName);
    long getGnssCapabilities();
    void removeGnssMeasurementsListener(in IGnssMeasurementsListener listener);

    boolean addGnssAntennaInfoListener(in IGnssAntennaInfoListener listener,
             String packageName, String featureId);
    void removeGnssAntennaInfoListener(in IGnssAntennaInfoListener listener);

    boolean addGnssNavigationMessageListener(in IGnssNavigationMessageListener listener,
             String packageName, String featureId);
    void removeGnssNavigationMessageListener(in IGnssNavigationMessageListener listener);

    int getGnssYearOfHardware();
    String getGnssHardwareModelName();

    int getGnssBatchSize(String packageName);
    boolean addGnssBatchingCallback(in IBatchedLocationCallback callback, String packageName, String featureId);
    void removeGnssBatchingCallback();
    boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName, String featureId);
    void flushGnssBatch(String packageName);
    boolean stopGnssBatch();
    void injectLocation(in Location location);

    List<String> getAllProviders();
    List<String> getProviders(in Criteria criteria, boolean enabledOnly);
    String getBestProvider(in Criteria criteria, boolean enabledOnly);
    ProviderProperties getProviderProperties(String provider);
    boolean isProviderPackage(String packageName);
    List<String> getProviderPackages(String provider);

    void setExtraLocationControllerPackage(String packageName);
    String getExtraLocationControllerPackage();
    void setExtraLocationControllerPackageEnabled(boolean enabled);
    boolean isExtraLocationControllerPackageEnabled();

    boolean isProviderEnabledForUser(String provider, int userId);
    boolean isLocationEnabledForUser(int userId);
    void setLocationEnabledForUser(boolean enabled, int userId);
    void addTestProvider(String name, in ProviderProperties properties, String packageName, String featureId);
    void removeTestProvider(String provider, String packageName, String featureId);
    void setTestProviderLocation(String provider, in Location location, String packageName, String featureId);
    void setTestProviderEnabled(String provider, boolean enabled, String packageName, String featureId);
    List<LocationRequest> getTestProviderCurrentRequests(String provider);
    LocationTime getGnssTimeMillis();

    boolean sendExtraCommand(String provider, String command, inout Bundle extras);

    // --- internal ---

    // for reporting callback completion
    void locationCallbackFinished(ILocationListener listener);

    // used by gts tests to verify whitelists
    String[] getBackgroundThrottlingWhitelist();
    String[] getIgnoreSettingsWhitelist();
}

LocationManagerService继承了ILocationManager.Stub,实现了ILocationManager.aidl里面所有的方法。

/**
 * The service class that manages LocationProviders and issues location
 * updates and alerts.
 */
public class LocationManagerService extends ILocationManager.Stub {
    //省略部分代码
    @Override
    public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
            PendingIntent intent, String packageName, String featureId, String listenerId) {
        //省略部分代码
    }
    //省略部分代码
}

也就是说LocationManagerService向上层提供了所有定位相关的API

framework层(java)

虽然LocationManagerService提供了很多定位相关的API,但它本省并不是Service,因为它继承的是ILocationManager.Stub,那它是怎么创建并能保持运行的呢,这依赖它的内部类LocationManagerService.Lifecycle

/**
 * The service class that manages LocationProviders and issues location
 * updates and alerts.
 */
public class LocationManagerService extends ILocationManager.Stub {
    
    /**
     * Controls lifecycle of LocationManagerService.
     */
    public static class Lifecycle extends SystemService {

        private final UserInfoHelper mUserInfoHelper;
        private final LocationManagerService mService;

        public Lifecycle(Context context) {
            super(context);
            mUserInfoHelper = new SystemUserInfoHelper(context);
            //代码1:创建LocationManagerService
            mService = new LocationManagerService(context, mUserInfoHelper);
        }
        
        @Override
        public void onStart() {
            // enable client caches by doing the first invalidate
            LocationManager.invalidateLocalLocationEnabledCaches();

            publishBinderService(Context.LOCATION_SERVICE, mService);
            // disable caching for whatever process contains LocationManagerService
            ((LocationManager) mService.mContext.getSystemService(LocationManager.class))
                    .disableLocalLocationEnabledCaches();
        }

        @Override
        public void onBootPhase(int phase) {
            if (phase == PHASE_SYSTEM_SERVICES_READY) {
                // the location service must be functioning after this boot phase
                mService.onSystemReady();
            } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
                // some providers rely on third party code, so we wait to initialize
                // providers until third party code is allowed to run
                //代码2
                mService.onSystemThirdPartyAppsCanStart();
            }
        }
        //省略部分代码
    }
    //省略部分代码
}

LocationManagerService.Lifecycle继承自SystemService,说明它是一个系统服务,并且随着系统的启动而启动,在SystemServer

public final class SystemServer {
    //省略部分代码
    /**
     * The main entry point from zygote.
     */
    public static void main(String[] args) {
        //被zygote进程调用
        new SystemServer().run();
    }
    //省略部分代码
    
    private void run() {
        //省略部分代码
        // Start services.
        try {
            t.traceBegin("StartServices");
            startBootstrapServices(t);
            startCoreServices(t);
            //这里启动LocationManagerService.Lifecycle
            startOtherServices(t);
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            t.traceEnd(); // StartServices
        }
        //省略部分代码
    }
    
        /**
     * Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
     */
    private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
        //省略部分代码
        t.traceBegin("StartLocationManagerService");
        //启动LocationManagerService.Lifecycle
        mSystemServiceManager.startService(LocationManagerService.Lifecycle.class);
        t.traceEnd();
        //省略部分代码
    }
}

LocationManagerService.Lifecycle被启动时,先执行它的构造方法,创建LocationManagerService对象,见代码1,此时LocationManagerService存活在LocationManagerService.Lifecycle中,相当于是一个Service了,以下将LocationManagerService.Lifecycle统称之为LocationManagerService

回到代码2处,当LocationManagerService启动完毕之后会执行onSystemThirdPartyAppsCanStart(),此方法内开始初始化Gnss

    private void onSystemThirdPartyAppsCanStart() {
        synchronized (mLock) {
            // prepare providers
            initializeProvidersLocked();
        }

        // initialize gnss last because it has no awareness of boot phases and blindly assumes that
        // all other location providers are loaded at initialization
        //此处初始化Gnss
        initializeGnss();
    }

	private void initializeGnss() {
        // Do not hold mLock when calling GnssManagerService#isGnssSupported() which calls into HAL.
        //代码3
        if (GnssManagerService.isGnssSupported()) {
            //只有设备支持Gnss才会初始化
            //创建GnssManagerService
            mGnssManagerService = new GnssManagerService(mContext, mAppOpsHelper, mSettingsHelper,
                    mAppForegroundHelper, mLocationUsageLogger);
            mGnssManagerService.onSystemReady();

            //创建LocationProviderManager,并且设置定位类型为GPS
            LocationProviderManager gnssManager = new LocationProviderManager(GPS_PROVIDER);
            synchronized (mLock) {
                mProviderManagers.add(gnssManager);
            }
            //设置locationProvider为GnssLocationProvider,也就是定位数据通过Gnss提供
            gnssManager.setRealProvider(mGnssManagerService.getGnssLocationProvider());

            // bind to geofence proxy
            //创建地理围栏并与GnssManagerService绑定
            IGpsGeofenceHardware gpsGeofenceHardware = mGnssManagerService.getGpsGeofenceProxy();
            if (gpsGeofenceHardware != null) {
                GeofenceProxy provider = GeofenceProxy.createAndBind(mContext, gpsGeofenceHardware);
                if (provider == null) {
                    Log.e(TAG, "unable to bind to GeofenceProxy");
                }
            }
        }
    }

jni层

代码3处,首先判断设备是否支持Gnss,判断方式是看设备是否有Gnss Hal Service在运行,具体见源码

    public static boolean isGnssSupported() {
        return GnssLocationProvider.isSupported();
    }
    public static boolean isSupported() {
        if (sStaticTestOverride) {
            return true;
        }
        ensureInitialized();
        return native_is_supported();
    }

	private static native boolean native_is_supported();

native源码对应在frameworks/base/services/core/jni/com_android_server_location_GnssLocationProvider.cpp

//声明gnssHal
sp<IGnss_V1_0> gnssHal = nullptr;

/* Initializes the GNSS service handle. */
static void android_location_GnssLocationProvider_set_gps_service_handle() {
    ALOGD("Trying IGnss_V2_1::getService()");
    //初始化gnssHal,即获取gnss hal service
    gnssHal_V2_1 = IGnss_V2_1::getService();
    if (gnssHal_V2_1 != nullptr) {
        gnssHal = gnssHal_V2_1;
        gnssHal_V2_0 = gnssHal_V2_1;
        gnssHal_V1_1 = gnssHal_V2_1;
        gnssHal = gnssHal_V2_1;
        return;
    }

    ALOGD("gnssHal 2.1 was null, trying 2.0");
    gnssHal_V2_0 = IGnss_V2_0::getService();
    if (gnssHal_V2_0 != nullptr) {
        gnssHal = gnssHal_V2_0;
        gnssHal_V1_1 = gnssHal_V2_0;
        return;
    }

    ALOGD("gnssHal 2.0 was null, trying 1.1");
    gnssHal_V1_1 = IGnss_V1_1::getService();
    if (gnssHal_V1_1 != nullptr) {
        gnssHal = gnssHal_V1_1;
        return;
    }

    ALOGD("gnssHal 1.1 was null, trying 1.0");
    gnssHal = IGnss_V1_0::getService();
}

static jboolean android_location_GnssLocationProvider_is_supported(
        JNIEnv* /* env */, jclass /* clazz */) {
    //gnssHal不为空,则支持gnss,否则不支持
    return (gnssHal != nullptr) ?  JNI_TRUE : JNI_FALSE;
}

//java-cpp函数映射
static const JNINativeMethod sMethods[] = {
     /* name, signature, funcPtr */
    //省略部分代码
    {"native_is_supported", "()Z", reinterpret_cast<void *>(
            android_location_GnssLocationProvider_is_supported)},
    //省略部分代码
};

这也就意味着,只要有Gnss Hal Service在运行,不管你有没有Gnss硬件,系统都会判定支持Gnss。

如果设备支持Gnss,则进行一系列的初始化,首先是创建GnssManagerService,然后创建LocationProviderManager,最后创建GeofenceProxy并与GnssManagerService绑定,这里的绑定实际上创建了GeofenceHardwareService,然后通过bindService()的方式与Context进程进行绑定

    @Nullable
    public static GeofenceProxy createAndBind(Context context, IGpsGeofenceHardware gpsGeofence) {
        GeofenceProxy proxy = new GeofenceProxy(context, gpsGeofence);
        if (proxy.register(context)) {
            return proxy;
        } else {
            return null;
        }
    }

    private boolean register(Context context) {
        if (mServiceWatcher.register()) {
            //context进程与GeofenceHardwareService进行绑定
            context.bindServiceAsUser(
                    new Intent(context, GeofenceHardwareService.class),
                    new GeofenceProxyServiceConnection(),
                    Context.BIND_AUTO_CREATE,
                    UserHandle.SYSTEM);
            return true;
        }

        return false;
    }

Gnss开机初始化的流程分析到这里,回到LocationManagerService.requestLocationUpdates()中,看看请求定位数据的流程

/**
 * The service class that manages LocationProviders and issues location
 * updates and alerts.
 */
public class LocationManagerService extends ILocationManager.Stub {
    //省略部分代码
    @Override
    public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
            PendingIntent intent, String packageName, String featureId, String listenerId) {
        if (request == null) {
            request = DEFAULT_LOCATION_REQUEST;
        }
        if (listenerId == null && intent != null) {
            listenerId = AppOpsManager.toReceiverId(intent);
        }
		//检查权限
        CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId,
                listenerId);
        identity.enforceLocationPermission();

        WorkSource workSource = request.getWorkSource();
        if (workSource != null && !workSource.isEmpty()) {
            mContext.enforceCallingOrSelfPermission(
                    Manifest.permission.UPDATE_DEVICE_STATS, null);
        }
        boolean hideFromAppOps = request.getHideFromAppOps();
        if (hideFromAppOps) {
            mContext.enforceCallingOrSelfPermission(
                    Manifest.permission.UPDATE_APP_OPS_STATS, null);
        }
        if (request.isLocationSettingsIgnored()) {
            mContext.enforceCallingOrSelfPermission(
                    Manifest.permission.WRITE_SECURE_SETTINGS, null);
        }
        boolean callerHasLocationHardwarePermission =
                mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
                        == PERMISSION_GRANTED;
        //创建请求
        LocationRequest sanitizedRequest = createSanitizedRequest(request,
                identity,
                callerHasLocationHardwarePermission);

        if (intent == null && listener == null) {
            throw new IllegalArgumentException("need either listener or intent");
        } else if (intent != null && listener != null) {
            throw new IllegalArgumentException(
                    "cannot register both listener and intent");
        }

        mLocationUsageLogger.logLocationApiUsage(
                LocationStatsEnums.USAGE_STARTED,
                LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
                packageName, request, listener != null, intent != null,
                /* geofence= */ null,
                mAppForegroundHelper.getImportance(identity.uid));

        synchronized (mLock) {
            Receiver receiver;
            //创建接收器,用于接受来自hal层返回的数据
            if (intent != null) {
                receiver = getReceiverLocked(intent, identity, workSource, hideFromAppOps);
            } else {
                receiver = getReceiverLocked(listener, identity, workSource, hideFromAppOps);
            }
            //请求定位数据
            if (receiver != null) {
                requestLocationUpdatesLocked(sanitizedRequest, receiver);
            }
        }
    }
    //省略部分代码
}

此方法主要完成了四步操作:

  • 检查权限
  • 创建请求体
  • 创建接收器,用于接受hal层返回的定位数据
  • 发送定位请求

继续看requestLocationUpdatesLocked()

	@GuardedBy("mLock")
    private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver) {
        // Figure out the provider. Either its explicitly request (legacy use cases), or
        // use the fused provider
        if (request == null) request = DEFAULT_LOCATION_REQUEST;
        String name = request.getProvider();
        //省略部分代码

        long identity = Binder.clearCallingIdentity();
        try {
            int userId = UserHandle.getUserId(receiver.mCallerIdentity.uid);
            if (!manager.isEnabled(userId) && !isSettingsExempt(record)) {
                // Notify the listener that updates are currently disabled - but only if the request
                // does not ignore location settings
                receiver.callProviderEnabledLocked(name, false);
            }
			//处理请求
            applyRequirementsLocked(name);

            // Update the monitoring here just in case multiple location requests were added to the
            // same receiver (this request may be high power and the initial might not have been).
            receiver.updateMonitoring(true);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @GuardedBy("mLock")
    private void applyRequirementsLocked(String providerName) {
        LocationProviderManager manager = getLocationProviderManager(providerName);
        if (manager != null) {
            //处理请求
            applyRequirementsLocked(manager);
        }
    }

	@GuardedBy("mLock")
    private void applyRequirementsLocked(LocationProviderManager manager) {
        ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName());
        ProviderRequest.Builder providerRequest = new ProviderRequest.Builder();

        // if provider is not active, it should not respond to requests

        //省略部分代码
		//发送请求
        manager.setRequest(providerRequest.build());
    }

    /**
     * Location provider manager, manages a LocationProvider.
     */
    class LocationProviderManager implements MockableLocationProvider.Listener {
        //省略部分代码
        public void setRequest(ProviderRequest request) {
            //发送请求
            mProvider.setRequest(request);
        }
        //省略部分代码
    }
    /**
     * Sets a new request and worksource for the provider.
     */
    public final void setRequest(ProviderRequest request) {
        // all calls into the provider must be moved onto the provider thread to prevent deadlock
        mExecutor.execute(obtainRunnable(AbstractLocationProvider::onSetRequest, this, request)
                .recycleOnUse());
    }

发送的请求最终在线程池中,交由AbstractLocationProvider的onSetRequest()方法完成,onSetRequest()是抽象方法,具体实现由AbstractLocationProvider的子类GnssLocationProvider完成

    @Override
    public void onSetRequest(ProviderRequest request) {
        sendMessage(SET_REQUEST, 0, new GpsRequest(request, request.workSource));
    }

    private void sendMessage(int message, int arg, Object obj) {
        // hold a wake lock until this message is delivered
        // note that this assumes the message will not be removed from the queue before
        // it is handled (otherwise the wake lock would be leaked).
        mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
        if (DEBUG) {
            Log.d(TAG, "WakeLock acquired by sendMessage(" + messageIdAsString(message) + ", " + arg
                    + ", " + obj + ")");
        }
        mHandler.obtainMessage(message, arg, 1, obj).sendToTarget();
    }

GnssLocationProvideronSetRequest()中通过Handler发送了一条Message,看一下此Message的处理

		@Override
        public void handleMessage(Message msg) {
            int message = msg.what;
            switch (message) {
                case SET_REQUEST:
                    //处理定位请求
                    GpsRequest gpsRequest = (GpsRequest) msg.obj;
                    handleSetRequest(gpsRequest.request, gpsRequest.source);
                    break;
                case INJECT_NTP_TIME:
                    mNtpTimeHelper.retrieveAndInjectNtpTime();
                    break;
                case REQUEST_LOCATION:
                    handleRequestLocation(msg.arg1 == 1, (boolean) msg.obj);
                    break;
                case DOWNLOAD_PSDS_DATA:
                    handleDownloadPsdsData();
                    break;
                case DOWNLOAD_PSDS_DATA_FINISHED:
                    mDownloadPsdsDataPending = STATE_IDLE;
                    break;
                case INITIALIZE_HANDLER:
                    handleInitialize();
                    break;
                case REPORT_LOCATION:
                    //代码4
                    handleReportLocation(msg.arg1 == 1, (Location) msg.obj);
                    break;
                case REPORT_SV_STATUS:
                    handleReportSvStatus((SvStatusInfo) msg.obj);
                    break;
                case UPDATE_LOW_POWER_MODE:
                    updateLowPowerMode();
                    break;
            }
            if (msg.arg2 == 1) {
                // wakelock was taken for this message, release it
                mWakeLock.release();
                if (DEBUG) {
                    Log.d(TAG, "WakeLock released by handleMessage(" + messageIdAsString(message)
                            + ", " + msg.arg1 + ", " + msg.obj + ")");
                }
            }
        }

    private void handleSetRequest(ProviderRequest request, WorkSource source) {
        mProviderRequest = request;
        mWorkSource = source;
        //更新Gnss状态
        updateEnabled();
        //当Gnss状态发生改变时需要调用此方法
        updateRequirements();
    }

这里做了两步操作,updateEnabled()updateRequirements(),先看updateEnabled()

	private void updateEnabled() {
        // Generally follow location setting for current user
        boolean enabled = mContext.getSystemService(LocationManager.class)
                .isLocationEnabledForUser(UserHandle.CURRENT);

        // ... but disable if PowerManager overrides
        enabled &= !mDisableGpsForPowerManager;

        // .. but enable anyway, if there's an active settings-ignored request (e.g. ELS)
        enabled |= (mProviderRequest != null && mProviderRequest.reportLocation
                && mProviderRequest.locationSettingsIgnored);

        // ... and, finally, disable anyway, if device is being shut down
        enabled &= !mShutdown;

        if (enabled == isGpsEnabled()) {
            return;
        }
		//gnss在开启和关闭的状态下做不同的更新处理
        if (enabled) {
            //处理gnss更新
            handleEnable();
        } else {
            handleDisable();
        }
    }

    private void handleEnable() {
        if (DEBUG) Log.d(TAG, "handleEnable");
		
        //在native层做一些初始化工作
        boolean inited = native_init();

        if (inited) {
            setGpsEnabled(true);
            //底层是否支持psds
            mSupportsPsds = native_supports_psds();

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

            mGnssMeasurementsProvider.onGpsEnabledChanged();
            mGnssNavigationMessageProvider.onGpsEnabledChanged();
            mGnssAntennaInfoProvider.onGpsEnabledChanged();
            mGnssBatchingProvider.enable();
            if (mGnssVisibilityControl != null) {
                mGnssVisibilityControl.onGpsEnabledChanged(/* isEnabled= */ true);
            }
        } else {
            setGpsEnabled(false);
            Log.w(TAG, "Failed to enable location provider");
        }
    }

具体native_init()native_supports_psds()native_set_agps_server()的实现内容见com_android_server_location_GnssLocationProvider.cpp

/* Initialization needed each time the GPS service is shutdown. */
//对应native_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.");
        return JNI_FALSE;
    }

    Return<bool> result = false;

    // Set top level IGnss.hal callback.
    //设置hal层回调,请求顺序:app->framework->hal,响应顺序:app<-framework<-hal
    sp<IGnssCallback_V2_1> gnssCbIface = new GnssCallback();
    if (gnssHal_V2_1 != nullptr) {
        result = gnssHal_V2_1->setCallback_2_1(gnssCbIface);
    } else if (gnssHal_V2_0 != nullptr) {
        result = gnssHal_V2_0->setCallback_2_0(gnssCbIface);
    } else if (gnssHal_V1_1 != nullptr) {
        result = gnssHal_V1_1->setCallback_1_1(gnssCbIface);
    } else {
        result = gnssHal->setCallback(gnssCbIface);
    }

    if (!checkHidlReturn(result, "IGnss setCallback() failed.")) {
        return JNI_FALSE;
    }

    // Set IGnssXtra.hal callback.
    if (gnssXtraIface == nullptr) {
        ALOGI("Unable to initialize IGnssXtra interface.");
    } else {
        sp<IGnssXtraCallback> gnssXtraCbIface = new GnssXtraCallback();
        result = gnssXtraIface->setCallback(gnssXtraCbIface);
        if (!checkHidlReturn(result, "IGnssXtra setCallback() failed.")) {
            gnssXtraIface = nullptr;
        }
    }

    // Set IAGnss.hal callback.
    if (agnssIface_V2_0 != nullptr) {
        sp<IAGnssCallback_V2_0> aGnssCbIface = new AGnssCallback_V2_0();
        auto agnssStatus = agnssIface_V2_0->setCallback(aGnssCbIface);
        checkHidlReturn(agnssStatus, "IAGnss 2.0 setCallback() failed.");
    } else if (agnssIface != nullptr) {
        sp<IAGnssCallback_V1_0> aGnssCbIface = new AGnssCallback_V1_0();
        auto agnssStatus = agnssIface->setCallback(aGnssCbIface);
        checkHidlReturn(agnssStatus, "IAGnss setCallback() failed.");
    } else {
        ALOGI("Unable to initialize IAGnss interface.");
    }

    // Set IGnssGeofencing.hal callback.
    sp<IGnssGeofenceCallback> gnssGeofencingCbIface = new GnssGeofenceCallback();
    if (gnssGeofencingIface != nullptr) {
        auto status = gnssGeofencingIface->setCallback(gnssGeofencingCbIface);
        checkHidlReturn(status, "IGnssGeofencing setCallback() failed.");
    } else {
        ALOGI("Unable to initialize IGnssGeofencing interface.");
    }

    // Set IGnssNi.hal callback.
    sp<IGnssNiCallback> gnssNiCbIface = new GnssNiCallback();
    if (gnssNiIface != nullptr) {
        auto status = gnssNiIface->setCallback(gnssNiCbIface);
        checkHidlReturn(status, "IGnssNi setCallback() failed.");
    } else {
        ALOGI("Unable to initialize IGnssNi interface.");
    }

    // Set IAGnssRil.hal callback.
    sp<IAGnssRilCallback> aGnssRilCbIface = new AGnssRilCallback();
    if (agnssRilIface != nullptr) {
        auto status = agnssRilIface->setCallback(aGnssRilCbIface);
        checkHidlReturn(status, "IAGnssRil setCallback() failed.");
    } else {
        ALOGI("Unable to initialize IAGnssRil interface.");
    }

    // Set IGnssVisibilityControl.hal callback.
    if (gnssVisibilityControlIface != nullptr) {
        sp<IGnssVisibilityControlCallback> gnssVisibilityControlCbIface =
                new GnssVisibilityControlCallback();
        result = gnssVisibilityControlIface->setCallback(gnssVisibilityControlCbIface);
        checkHidlReturn(result, "IGnssVisibilityControl setCallback() failed.");
    }

    // Set IMeasurementCorrections.hal callback.
    if (gnssCorrectionsIface_V1_1 != nullptr) {
            sp<IMeasurementCorrectionsCallback> gnssCorrectionsIfaceCbIface =
                    new MeasurementCorrectionsCallback();
            result = gnssCorrectionsIface_V1_1->setCallback(gnssCorrectionsIfaceCbIface);
            checkHidlReturn(result, "IMeasurementCorrections 1.1 setCallback() failed.");
    } else if (gnssCorrectionsIface_V1_0 != nullptr) {
        sp<IMeasurementCorrectionsCallback> gnssCorrectionsIfaceCbIface =
                new MeasurementCorrectionsCallback();
        result = gnssCorrectionsIface_V1_0->setCallback(gnssCorrectionsIfaceCbIface);
        checkHidlReturn(result, "IMeasurementCorrections 1.0 setCallback() failed.");
    } else {
        ALOGI("Unable to find IMeasurementCorrections.");
    }

    return JNI_TRUE;
}

//对应native_support_psds
static jboolean android_location_GnssLocationProvider_supports_psds(
        JNIEnv* /* env */, jobject /* obj */) {
    //判断gnssXtraIface服务是否存在,存在则支持,否则不支持
    return (gnssXtraIface != nullptr) ? JNI_TRUE : JNI_FALSE;
}

//对应native_set_agps_server
static void android_location_GnssLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */,
        jint type, jstring hostname, jint port) {
    if (agnssIface_V2_0 != nullptr) {
        AGnssDispatcher::setServer<IAGnss_V2_0, IAGnssCallback_V2_0>(agnssIface_V2_0, env, type,
                hostname, port);
    } else if (agnssIface != nullptr) {
        AGnssDispatcher::setServer<IAGnss_V1_0, IAGnssCallback_V1_0>(agnssIface, env, type,
                hostname, port);
    } else {
        ALOGE("%s: IAGnss interface not available.", __func__);
        return;
    }
}

再看updateRequirements()

    // Called when the requirements for GPS may have changed
    private void updateRequirements() {
        if (mProviderRequest == null || mWorkSource == null) {
            return;
        }

        if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest);
        if (mProviderRequest.reportLocation && isGpsEnabled()) {
            //省略部分代码

            // apply request to GPS engine
            if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
                // change period and/or lowPowerMode
                if (!setPositionMode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
                        mFixInterval, 0, 0, mLowPowerMode)) {
                    Log.e(TAG, "set_position_mode failed in updateRequirements");
                }
            } else if (!mStarted) {
                // start GPS
                //开始定位
                startNavigating();
            } else {
                // GNSS Engine is already ON, but no GPS_CAPABILITY_SCHEDULING
                mAlarmManager.cancel(mTimeoutIntent);
                if (mFixInterval >= NO_FIX_TIMEOUT) {
                    // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
                    // and our fix interval is not short
                    mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                            SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
                }
            }
        } else {
            updateClientUids(new WorkSource());

            stopNavigating();
            mAlarmManager.cancel(mWakeupIntent);
            mAlarmManager.cancel(mTimeoutIntent);
        }
    }

    private void startNavigating() {
        if (!mStarted) {
           	//省略部分代码
            if (!setPositionMode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
                    interval, 0, 0, mLowPowerMode)) {
                setStarted(false);
                Log.e(TAG, "set_position_mode failed in startNavigating()");
                return;
            }
            //native_start()开启底层定位工作
            if (!native_start()) {
                setStarted(false);
                Log.e(TAG, "native_start failed in startNavigating()");
                return;
            }

           //省略部分代码
        }
    }

查看native_start()实现

static jboolean android_location_GnssLocationProvider_start(JNIEnv* /* env */, jobject /* obj */) {
    if (gnssHal == nullptr) {
        return JNI_FALSE;
    }
	//调用hal层服务开启定位
    auto result = gnssHal->start();
    return checkHidlReturn(result, "IGnss start() failed.");
}

hal层

上述分析可以看出,所有操作都是从java->jni->native->hal,现在我们来看看hal里面的实现,在hardware/interfaces/gnss/1.0/default/Gnss.cpp,因为移植的1.0的hal服务,所以在1.0目录中,对应还有1.1, 2.0, 2.1。主要看我们前面分析过的核心方法

//接收硬件返回的定位数据
void Gnss::locationCb(GpsLocation* location) {
    if (sGnssCbIface == nullptr) {
        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
        return;
    }

    if (location == nullptr) {
        ALOGE("%s: Invalid location from GNSS HAL", __func__);
        return;
    }

    android::hardware::gnss::V1_0::GnssLocation gnssLocation = convertToGnssLocation(location);
    auto ret = sGnssCbIface->gnssLocationCb(gnssLocation);
    if (!ret.isOk()) {
        ALOGE("%s: Unable to invoke callback", __func__);
    }
}

// Methods from ::android::hardware::gnss::V1_0::IGnss follow.
//hal层回调实现
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);
}
//开始定位
Return<bool> Gnss::start()  {
    if (mGnssIface == nullptr) {
        ALOGE("%s: Gnss interface is unavailable", __func__);
        return false;
    }

    return (mGnssIface->start() == 0);
}
//停止定位
Return<bool> Gnss::stop()  {
    if (mGnssIface == nullptr) {
        ALOGE("%s: Gnss interface is unavailable", __func__);
        return false;
    }

    return (mGnssIface->stop() == 0);
}

除了上述几个方法外,还有很多方法,有兴趣可以自行查阅。我们可以看到,所有hal层的方法里都是通过mGnssIface来完成的,mGnssIface是一个结构体,定义在hardware/libhardware/include/hardware/gps.h

/** Represents the standard GPS interface. */
typedef struct {
    /** set to sizeof(GpsInterface) */
    size_t          size;
    /**
     * Opens the interface and provides the callback routines
     * to the implementation of this interface.
     */
    int   (*init)( GpsCallbacks* callbacks );

    /** Starts navigating. */
    int   (*start)( void );

    /** Stops navigating. */
    int   (*stop)( void );

    /** Closes the interface. */
    void  (*cleanup)( void );

    /** Injects the current time. */
    int   (*inject_time)(GpsUtcTime time, int64_t timeReference,
                         int uncertainty);

    /**
     * Injects current location from another location provider (typically cell
     * ID). Latitude and longitude are measured in degrees expected accuracy is
     * measured in meters
     */
    int  (*inject_location)(double latitude, double longitude, float accuracy);

    /**
     * Specifies that the next call to start will not use the
     * information defined in the flags. GPS_DELETE_ALL is passed for
     * a cold start.
     */
    void  (*delete_aiding_data)(GpsAidingData flags);

    /**
     * min_interval represents the time between fixes in milliseconds.
     * preferred_accuracy represents the requested fix accuracy in meters.
     * preferred_time represents the requested time to first fix in milliseconds.
     *
     * 'mode' parameter should be one of GPS_POSITION_MODE_MS_BASED
     * or GPS_POSITION_MODE_STANDALONE.
     * It is allowed by the platform (and it is recommended) to fallback to
     * GPS_POSITION_MODE_MS_BASED if GPS_POSITION_MODE_MS_ASSISTED is passed in, and
     * GPS_POSITION_MODE_MS_BASED is supported.
     */
    int   (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
            uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);

    /** Get a pointer to extension information. */
    const void* (*get_extension)(const char* name);
} GpsInterface;

gps.h作为gnssHal与hardware通信的标准,硬件只有实现了这个文件,hal层才能对应的拿到gnss数据,进而再返回framework层乃至app层,所以硬件厂商必须实现这个文件里面所有的方法,具体怎么实现由各个厂商自行决定,这个有点儿类似于jni.h。

数据回调

与此同时,hal层接收硬件层返回的数据是在locationCb(),此方法拿到定位数据后,层层往上回调,先是到达com_android_server_location_GnssLocationProvider.cppgnssLocationCb()

Return<void> GnssCallback::gnssLocationCbImpl(const T& location) {
    JNIEnv* env = getJniEnv();

    jobject jLocation = translateGnssLocation(env, location);
	//调用java方法,将数据回调给上层,并且java方法的名称为reportLocation,参数为boolean/Location,返回值为void
    env->CallVoidMethod(mCallbacksObj,
                        method_reportLocation,
                        boolToJbool(hasLatLong(location)),
                        jLocation);
    checkAndClearExceptionFromCallback(env, __FUNCTION__);
    env->DeleteLocalRef(jLocation);
    return Void();
}

Return<void> GnssCallback::gnssLocationCb(const GnssLocation_V1_0& location) {
    //来自hal层的回调
    return gnssLocationCbImpl<GnssLocation_V1_0>(location);
}

/* One time initialization at system boot */
static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
    // Initialize the top level gnss HAL handle.
    android_location_GnssLocationProvider_set_gps_service_handle();

    // Cache methodIDs and class IDs.
    //method_reportLocation对应GnssLocationProvider中的reportLocation(boolean hasLatLong,Location location)
    method_reportLocation = env->GetMethodID(clazz, "reportLocation",
            "(ZLandroid/location/Location;)V");
}

最终回调给GnssLocationProviderreportLocation()方法来处理

    @NativeEntryPoint
    private void reportLocation(boolean hasLatLong, Location location) {
        sendMessage(REPORT_LOCATION, hasLatLong ? 1 : 0, location);
    }

java层收到数据后,使用Handler发送Message统一处理,最终在handleReportLocation()中处理,见上面代码4

	private void handleReportLocation(boolean hasLatLong, Location location) {
        //省略部分代码

        reportLocation(location);

        //省略部分代码
    }

    /**
     * Call this method to report a new location.
     */
    protected void reportLocation(Location location) {
        Listener listener = mInternalState.get().listener;
        if (listener != null) {
            long identity = Binder.clearCallingIdentity();
            try {
                listener.onReportLocation(location);
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

回调到LocationManagerService.LocationProviderManager

        @GuardedBy("mLock")
        @Override
        public void onReportLocation(Location location) {
            // don't validate mock locations
            //省略部分代码

            handleLocationChangedLocked(this, location, mLocationFudger.createCoarse(location));
        }
	@GuardedBy("mLock")
    private void handleLocationChangedLocked(LocationProviderManager manager, Location fineLocation,
            Location coarseLocation) {
       		//省略部分代码

            if (shouldBroadcastSafeLocked(location, r.mLastFixBroadcast, r, now)) {
                r.mLastFixBroadcast = location;

                // appops check should always be right before delivery
                if (!mAppOpsHelper.noteLocationAccess(receiver.mCallerIdentity)) {
                    continue;
                }
				//通过之前创建的Receiver,继续向上回调
                if (!receiver.callLocationChangedLocked(location)) {
                    receiverDead = true;
                }
                r.mRealRequest.decrementNumUpdates();
            }

            //省略部分代码
    }
	public boolean callLocationChangedLocked(Location location) {
            if (mListener != null) {
                try {
                    //回调给客户端,之前我们分析的LocationManager通过AIDL调用LocationManagerService的方法
                    mListener.onLocationChanged(new Location(location));
                    // call this after broadcasting so we do not increment
                    // if we throw an exception.
                    incrementPendingBroadcastsLocked();
                } catch (RemoteException e) {
                    return false;
                }
            } else {
                Intent locationChanged = new Intent();
                locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED,
                        new Location(location));
                try {
                    mPendingIntent.send(mContext, 0, locationChanged, this, mHandler,
                            CallerIdentity.asPermission(mCallerIdentity.permissionLevel),
                            PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
                    // call this after broadcasting so we do not increment
                    // if we throw an exception.
                    incrementPendingBroadcastsLocked();
                } catch (PendingIntent.CanceledException e) {
                    return false;
                }
            }
            return true;
        }

回调给客户端LocationManager

        @Override
        public void onLocationChanged(Location location) {
            Executor currentExecutor = mExecutor;
            if (currentExecutor == null) {
                return;
            }
			
            PooledRunnable runnable =
                    obtainRunnable(LocationListenerTransport::acceptLocation, this, currentExecutor,
                            location).recycleOnUse();
            try {
                currentExecutor.execute(runnable);
            } catch (RejectedExecutionException e) {
                runnable.recycle();
                locationCallbackFinished();
                throw e;
            }
        }
        private void acceptLocation(Executor currentExecutor, Location location) {
            try {
                if (currentExecutor != mExecutor) {
                    return;
                }

                // we may be under the binder identity if a direct executor is used
                long identity = Binder.clearCallingIdentity();
                try {
                    //这里的mListener就是app层设置的listener
                    mListener.onLocationChanged(location);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            } finally {
                locationCallbackFinished();
            }
        }

到这里,通过app层传进来的Listener再将数据回调到app层,即代码5处,整个gnss定位,从请求定位到收到定位数据的整体工作就完成了。

时序图

gnss.png

总结

整个gnss工作流程还是很复杂的,本文只是从发送请求到收到数据这一流程进行的分析,实际gnss还有很多配置项和辅助定位功能,感兴趣可以自行研究一下,相信对开发app定位功能会有一定的帮助。