• 欢迎访问开心洋葱网站,在线教程,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站,欢迎加入开心洋葱 QQ群
  • 为方便开心洋葱网用户,开心洋葱官网已经开启复制功能!
  • 欢迎访问开心洋葱网站,手机也能访问哦~欢迎加入开心洋葱多维思维学习平台 QQ群
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏开心洋葱吧~~~~~~~~~~~~~!
  • 由于近期流量激增,小站的ECS没能经的起亲们的访问,本站依然没有盈利,如果各位看如果觉着文字不错,还请看官给小站打个赏~~~~~~~~~~~~~!

Android LocationManagerService启动(一)

Android hlhuang 2607次浏览 0个评论

Location服务是系统中很重要的一个服务,几乎当前所有的App都会用到这个服务。

首先看代码在Android源码的位置

Android API

frameworks/base/location

LocationManagerService

frameworks/base/services/core/java/com/android/server/location
frameworks/base/services/core/java/com/android/server/LocationManagerService.java

SystemServer

作为一个系统级别服务,启动肯定是在SystemServer中进行。

代码入口:frameworks/base/services/java/com/android/server/SystemServer.java
启动LocationManagerService的代码在startOtherServices()函数里面

执行流程如下

  1. 创建LocationManagerService对象
  2. 将创建好的的对象加入到ServiceManager里面
  3. 调用LocationManagerServicesystemRunning()函数初始化相关的Provider
private void startOtherServices() {
    ////////////////////
    LocationManagerService location = null;
    traceBeginAndSlog("StartLocationManagerService");
    try {
        location = new LocationManagerService(context);
        ServiceManager.addService(Context.LOCATION_SERVICE, location);
    } catch (Throwable e) {
        reportWtf("starting Location Manager", e);
    }
    traceEnd();
    // These are needed to propagate to the runnable below.
    final LocationManagerService locationF = location;
    traceBeginAndSlog("MakeLocationServiceReady");
    try {
        if (locationF != null) locationF.systemRunning();
    } catch (Throwable e) {
        reportWtf("Notifying Location Service running", e);
    }
    traceEnd();
    ////////////////////
}

LocationManagerService

从ServiceManager启动后,会调用systemRunning()方法,这个函数里面会初始化所有的可用的Providers
代码路径:frameworks/base/services/core/java/com/android/server/LocationManagerService.java

构造函数

构造函数很简单,除了初始化变量外,就给PackageManager设置了一个PackageProvider

public LocationManagerService(Context context) {
    super();
    mContext = context;
    mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
    // Let the package manager query which are the default location
    // providers as they get certain permissions granted by default.
    PackageManagerInternal packageManagerInternal = LocalServices.getService(
            PackageManagerInternal.class);
    packageManagerInternal.setLocationPackagesProvider(
            new PackageManagerInternal.PackagesProvider() {
                @Override
                public String[] getPackages(int userId) {
                    return mContext.getResources().getStringArray(
                            com.android.internal.R.array.config_locationProviderPackageNames);
                }
            });
    if (D) Log.d(TAG, "Constructed");
    // most startup is deferred until systemRunning()
}

systemRunning()

作为LocationManagerService的入口函数,主要做以下几部分工作

  1. 初始化成员变量,主要是个各种需要用的Manager
  2. 初始化Provider
  3. 注册Observer,主要是包括Settings,UserChange等
public void systemRunning() {
    synchronized (mLock) {
        if (D) Log.d(TAG, "systemRunning()");
        // prepare providers
        loadProvidersLocked();
        updateProvidersLocked();
    }
    // listen for settings changes
    // ..... //
    // listen for user change
    // ..... //
}

我们主要看第二点,包括了各种Provider的初始化

loadProvidersLocked

加载顺序如下

1. PassiveProvider,必须
2. GnssLocationProvider,如果有,则加载
3. FuseProvider检查,这里比较重要,如果通不过,会跑出异常,不会进行下面的步骤(systemRunning会结束)
4. Bind NetworkProvider,第三方Provider
5. Bind Fused provider
6. Bind Geocoder provider
7. Bind Geofence provider

另外,针对每一个Provider,创建的步骤大致都是以下几个步骤

{
    XxxProvider xxxProvider = new XxxProvider(this);
    addProviderLocked(xxxProvider);
    mEnabledProviders.add(xxxProvider.getName());
    // or
    mRealProviders.put(LocationManager.Xxx_PROVIDER, xxxProvider);
    mXxxProvider = xxxProvider;
}

部分Provider初始化相对复杂一点,但是整体的逻辑一致。我们这里重点分析GnssProvider

private void loadProvidersLocked() {
    // create a passive location provider, which is always enabled
    PassiveProvider passiveProvider = new PassiveProvider(this);
    addProviderLocked(passiveProvider);
    mEnabledProviders.add(passiveProvider.getName());
    mPassiveProvider = passiveProvider;

    if (GnssLocationProvider.isSupported()) {
        // 创建GnssProvider(老版本的Android上是GPS,后面整合成了GNSS,支持不同类型的导航系统)
        GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this,
                mLocationHandler.getLooper());
        mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
        mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
        mGnssMetricsProvider = gnssProvider.getGnssMetricsProvider();
        mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
        mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
        addProviderLocked(gnssProvider);
        mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProvider);
        mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
        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();
    ArrayList<String> providerPackageNames = new ArrayList<>();
    String[] pkgs = resources.getStringArray(
            com.android.internal.R.array.config_locationProviderPackageNames);
    if (D) {
        Log.d(TAG, "certificates for location providers pulled from: " +
                Arrays.toString(pkgs));
    }
    if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));

      // 注意这里如果没有找到FuseProvider,会抛出异常,结束这个初始化流程
    ensureFallbackFusedProviderPresentLocked(providerPackageNames);

    // bind to network provider
    // bind to fused provider
    // bind to geocoder provider
    // bind to geofence provider
    // bind to hardware activity recognition
}

updateProvidersLocked

上一个步骤仅仅只是进行了Provider的初始化操作,这里会调用Provider的enable方法,启用相关的Provider,主要调用
updateProviderListenersLocked(String provider, boolean enabled)

private void updateProvidersLocked() {
    boolean changesMade = false;
    // 遍历所有的Provider
    for (int i = mProviders.size() - 1; i >= 0; i--) {
        LocationProviderInterface p = mProviders.get(i);
        boolean isEnabled = p.isEnabled();
        String name = p.getName();
        // 通过当前用户的Settings来判断是否需要启动这个Provider
        boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
        if (isEnabled && !shouldBeEnabled) {
            // 如果已经启动并且是不需要被启动,就会关闭
            // 并且清除之前的记录
            updateProviderListenersLocked(name, false);
            // If any provider has been disabled, clear all last locations for all providers.
            // This is to be on the safe side in case a provider has location derived from
            // this disabled provider.
            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);
    }
}

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));
        }
    }
    // 根据传入的参数,确定是开启还是关闭相关的Provider
    if (enabled) {
        p.enable();
        if (listeners > 0) {
            // 如果存在Locatoin listener,会调用下面的方法
            applyRequirementsLocked(provider);
        }
    } else {
        p.disable();
    }
}

applyRequirementsLocked

这里会根据请求的Record的参数,来向具体的Provider发起位置信息请求。

private void applyRequirementsLocked(String provider) {
    LocationProviderInterface p = mProvidersByName.get(provider);
    if (p == null) return;
    ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
    WorkSource worksource = new WorkSource();
    ProviderRequest providerRequest = new ProviderRequest();
    ContentResolver resolver = mContext.getContentResolver();
    long backgroundThrottleInterval = Settings.Global.getLong(
            resolver,
            Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
            DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
    // initialize the low power mode to true and set to false if any of the records requires
    providerRequest.lowPowerMode = true;
    if (records != null) {
        for (UpdateRecord record : records) {
            if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
                if (checkLocationAccess(
                        record.mReceiver.mIdentity.mPid,
                        record.mReceiver.mIdentity.mUid,
                        record.mReceiver.mIdentity.mPackageName,
                        record.mReceiver.mAllowedResolutionLevel)) {
                    LocationRequest locationRequest = record.mRealRequest;
                    long interval = locationRequest.getInterval();
                    if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
                        if (!record.mIsForegroundUid) {
                            interval = Math.max(interval, backgroundThrottleInterval);
                        }
                        if (interval != locationRequest.getInterval()) {
                            locationRequest = new LocationRequest(locationRequest);
                            locationRequest.setInterval(interval);
                        }
                    }
                    record.mRequest = locationRequest;
                    providerRequest.locationRequests.add(locationRequest);
                    if (!locationRequest.isLowPowerMode()) {
                        providerRequest.lowPowerMode = false;
                    }
                    if (interval < providerRequest.interval) {
                        providerRequest.reportLocation = true;
                        providerRequest.interval = interval;
                    }
                }
            }
        }
        if (providerRequest.reportLocation) {
            // calculate who to blame for power
            // This is somewhat arbitrary. We pick a threshold interval
            // that is slightly higher that the minimum interval, and
            // spread the blame across all applications with a request
            // under that threshold.
            long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
            for (UpdateRecord record : records) {
                if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
                    LocationRequest locationRequest = record.mRequest;
                    // Don't assign battery blame for update records whose
                    // client has no permission to receive location data.
                    if (!providerRequest.locationRequests.contains(locationRequest)) {
                        continue;
                    }
                    if (locationRequest.getInterval() <= thresholdInterval) {
                        if (record.mReceiver.mWorkSource != null
                                && isValidWorkSource(record.mReceiver.mWorkSource)) {
                            worksource.add(record.mReceiver.mWorkSource);
                        } else {
                            // Assign blame to caller if there's no WorkSource associated with
                            // the request or if it's invalid.
                            worksource.add(
                                    record.mReceiver.mIdentity.mUid,
                                    record.mReceiver.mIdentity.mPackageName);
                        }
                    }
                }
            }
        }
    }
    if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
    // 最终调用Provider的setRequest方法,进入到Provider的内部流程
    p.setRequest(providerRequest, worksource);
}

总结

总结下LocationManagerService里面初始化的流程

graph TD systemRunning –> loadProvidersLocked subgraph loadProvidersLockedProcess loadProvidersLocked –> loadPassiveProvider loadPassiveProvider –> loadGnssProvider loadGnssProvider –> checkFusedProvider checkFusedProvider –> bindNetworkProvider bindNetworkProvider –> bindGeocoderProvider bindGeocoderProvider –> bindGeofenceProvider bindGeofenceProvider –> bindHardwareActivityRecogneition bindHardwareActivityRecogneition –> updateProvidersLocked end subgraph updateProvidersLockedProcess updateProvidersLocked –> updateProviderListenersLocked updateProviderListenersLocked –> provider.enable provider.enable –> applyRequirementsLocked applyRequirementsLocked –> provider.setRequest end

备注:
上面代码基于Android9 AOSP源码


开心洋葱 , 版权所有丨如未注明 , 均为原创丨未经授权请勿修改 , 转载请注明Android LocationManagerService启动(一)
喜欢 (0)

您必须 登录 才能发表评论!

加载中……