专栏首页程序猿的那点事Android GPS学习 (一) :GPS 启动流程

Android GPS学习 (一) :GPS 启动流程

一、Settings

打开GPS的方法往数据库里面写值,然后framework层读取值再做相应处理。

packages/apps/Settings/src/com/android/settings/location/LocationSwitchBarController.java

public void onSwitchChanged(Switch switchView, boolean isChecked) {
    mLocationEnabler.setLocationEnabled(isChecked);
}

/packages/apps/Settings/src/com/android/settings/location/LocationEnabler.java

void setLocationMode(int mode) {
    final int currentMode = Settings.Secure.getInt(mContext.getContentResolver(),
            Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
    if (isRestricted()) {
        // Location toggling disabled by user restriction. Read the current location mode to
        // update the location master switch.
        if (Log.isLoggable(TAG, Log.INFO)) {
            Log.i(TAG, "Restricted user, not setting location mode");
        }
        if (mListener != null) {
            mListener.onLocationModeChanged(currentMode, true);
        }
        return;
    }

    updateLocationMode(mContext, currentMode, mode, ActivityManager.getCurrentUser(),
            Settings.Secure.LOCATION_CHANGER_SYSTEM_SETTINGS);
    refreshLocationMode();
}

二、framework

LocationManagerService的systemRunning方法中会监听setting数据库中的location_providers_allowed字段值的变化,

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

// listen for settings changes
mContext.getContentResolver().registerContentObserver(
        Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
        new ContentObserver(mLocationHandler) {
            @Override
            public void onChange(boolean selfChange) {
                synchronized (mLock) {
                    updateProvidersLocked();
                }
            }
        }, UserHandle.USER_ALL);

如果该值有变化,则调用updateProvidersLocked方法。

private void updateProvidersLocked() {
    boolean changesMade = false;
    for (int i = mProviders.size() - 1; i >= 0; i--) {
        LocationProviderInterface p = mProviders.get(i);
        boolean isEnabled = p.isEnabled();
        String name = p.getName();
        boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
        if (isEnabled && !shouldBeEnabled) {
            updateProviderListenersLocked(name, false);
            mLastLocation.clear();
            mLastLocationCoarseInterval.clear();
            changesMade = true;
        } else if (!isEnabled && shouldBeEnabled) {
            updateProviderListenersLocked(name, true);
            changesMade = true;
        }
    }
    if (changesMade) {
        mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
                UserHandle.ALL);
        mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
                UserHandle.ALL);
    }
}

在updateProvidersLocked方法中,如果支持gps,调用updateProviderListenersLocked方法。

private void updateProviderListenersLocked(String provider, boolean enabled) {
    int listeners = 0;

    LocationProviderInterface p = mProvidersByName.get(provider);
    if (p == null) return;

    ArrayList<Receiver> deadReceivers = null;

    ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
    if (records != null) {
        for (UpdateRecord record : records) {
            if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
                // Sends a notification message to the receiver
                if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
                    if (deadReceivers == null) {
                        deadReceivers = new ArrayList<>();
                    }
                    deadReceivers.add(record.mReceiver);
                }
                listeners++;
            }
        }
    }

    if (deadReceivers != null) {
        for (int i = deadReceivers.size() - 1; i >= 0; i--) {
            removeUpdatesLocked(deadReceivers.get(i));
        }
    }

    if (enabled) {
        p.enable();
        if (listeners > 0) {
            applyRequirementsLocked(provider);
        }
    } else {
        p.disable();
    }
}

GnssLocationProvider的enable方法如下:

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

GnssLocationProvider的enable方法如下:

public void enable() {
    synchronized (mLock) {
        if (mEnabled) return;
        mEnabled = true;
    }

    sendMessage(ENABLE, 1, null);
}

handlenable就是ENABLE的消息处理函数:

private void handleEnable() {
    if (DEBUG) Log.d(TAG, "handleEnable");

    boolean enabled = native_init();

    if (enabled) {
        mSupportsXtra = native_supports_xtra();

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

        mGnssMeasurementsProvider.onGpsEnabledChanged();
        mGnssNavigationMessageProvider.onGpsEnabledChanged();
        mGnssBatchingProvider.enable();
    } else {
        synchronized (mLock) {
            mEnabled = false;
        }
        Log.w(TAG, "Failed to enable location provider");
    }
}

三、HAL

native_init对应jni中的android_location_GpsLocationProvider_init函数,在该函数中调用了 sGpsInterface->init(&sGpsCallbacks),

frameworks/base/services/core/jni/com_android_server_location_GnssLocationProvider.cpp

{"native_init", "()Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_init)},
static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj) {
    /*
     * This must be set before calling into the HAL library.
     */
    if (!mCallbacksObj)
        mCallbacksObj = env->NewGlobalRef(obj);

    /*
     * Fail if the main interface fails to initialize
     */
    if (gnssHal == nullptr) {
        ALOGE("Unable to Initialize GNSS HAL\n");
        return JNI_FALSE;
    }

    sp<IGnssCallback> gnssCbIface = new GnssCallback();

    Return<bool> result = false;
    if (gnssHal_V1_1 != nullptr) {
        result = gnssHal_V1_1->setCallback_1_1(gnssCbIface);
    } else {
        result = gnssHal->setCallback(gnssCbIface);
    }
    if (!result.isOk() || !result) {
        ALOGE("SetCallback for Gnss Interface fails\n");
        return JNI_FALSE;
    }

    sp<IGnssXtraCallback> gnssXtraCbIface = new GnssXtraCallback();
    if (gnssXtraIface == nullptr) {
        ALOGE("Unable to initialize GNSS Xtra interface\n");
    } else {
        result = gnssXtraIface->setCallback(gnssXtraCbIface);
        if (!result.isOk() || !result) {
            gnssXtraIface = nullptr;
            ALOGI("SetCallback for Gnss Xtra Interface fails\n");
        }
    }

    sp<IAGnssCallback> aGnssCbIface = new AGnssCallback();
    if (agnssIface != nullptr) {
        agnssIface->setCallback(aGnssCbIface);
    } else {
        ALOGI("Unable to Initialize AGnss interface\n");
    }

    sp<IGnssGeofenceCallback> gnssGeofencingCbIface = new GnssGeofenceCallback();
    if (gnssGeofencingIface != nullptr) {
      gnssGeofencingIface->setCallback(gnssGeofencingCbIface);
    } else {
        ALOGI("Unable to initialize GNSS Geofencing interface\n");
    }

    sp<IGnssNiCallback> gnssNiCbIface = new GnssNiCallback();
    if (gnssNiIface != nullptr) {
        gnssNiIface->setCallback(gnssNiCbIface);
    } else {
        ALOGI("Unable to initialize GNSS NI interface\n");
    }

    sp<IAGnssRilCallback> aGnssRilCbIface = new AGnssRilCallback();
    if (agnssRilIface != nullptr) {
        agnssRilIface->setCallback(aGnssRilCbIface);
    } else {
        ALOGI("Unable to Initialize AGnss Ril interface\n");
    }

    return JNI_TRUE;
}

这是将jni的一些函数作为参数传递到native c 空间中去,这样在native c中如果有可用数据将通过回调的方式调用到jni中的函数。简单的看一下 location_callback的定义:

struct GnssCallback : public IGnssCallback {
    Return<void> gnssLocationCb(const GnssLocation& location) override;
    Return<void> gnssStatusCb(const IGnssCallback::GnssStatusValue status) override;
    Return<void> gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override;
    Return<void> gnssNmeaCb(int64_t timestamp, const android::hardware::hidl_string& nmea) override;
    Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override;
    Return<void> gnssAcquireWakelockCb() override;
    Return<void> gnssReleaseWakelockCb() override;
    Return<void> gnssRequestTimeCb() override;
    Return<void> gnssRequestLocationCb(const bool independentFromGnss) override;
    Return<void> gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override;

    // New in 1.1
    Return<void> gnssNameCb(const android::hardware::hidl_string& name) override;

    // TODO(b/73306084): Reconsider allocation cost vs threadsafety on these statics
    static const char* sNmeaString;
    static size_t sNmeaStringLength;
};

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • WifiDisplay开启流程

    我们先来看一下WifiDisplay的代码,先从UI看起。 WifiDisplay是在Wifi P2P的基础上发展而来的,他的功能实现也离不开P2P。所以在W...

    用户7557625
  • 高通 wlan 调试抓取日志大全

    最近也分析了一个高通wifi,bt 没用的问题, 注意分析过程中,高度和硬件或射频同事保持密切联系,多去骚扰他们。 因为,高通wifi/bt 相关的,只要硬件及...

    用户7557625
  • Android开启热点后作为路由器,获取AP端IP地址

    最近在做类似面对面通信,需要一台手机作为AP端开启热点,另一台手机作为STA端连接热点,然后AP端告诉STA端它的IP地址,进行socket通信。 手机在联网...

    用户7557625
  • 快速掌握并发编程---Semaphore原理和实战

    停车场:停车场只有2个车位,即同时只能容纳2辆车,车辆都是停一会再走的,如何保证同一时刻最多有2个车停在停车位?请用代码实现。

    田维常
  • Arcgis For Android之GPS定位实现

    lzugis
  • Golang Leetcode 896. Monotonic Array.go

    版权声明:原创勿转 https://blog.csdn.net/anakinsun/arti...

    anakinsun
  • 关系型数据库设计浅谈

    简称概念模型,是面向数据库用户的现实世界的模型,主要用来描述世界的概念化结构,它使数据库的设计人员在设计的初始阶段,摆脱计算机系统及DBMS的具体技术问题,集中...

    IT_Skywalker
  • ConcurrentHashMap源码解析(JDK1.8)

    package java.util.concurrent; import java.io.ObjectStreamField; import java.io....

    武培轩
  • ThreadPoolExecutor介绍

    综上,getAndIncrement() 方法并不是原子操作。 只是保证了他和其他函数对 value 值得更新都是有效的。 整个方法本身并不是线程安全的,但...

    提莫队长
  • MySQL binlog

    【转载请注明出处】:https://cloud.tencent.com/developer/article/1632663

    后端老鸟

扫码关注云+社区

领取腾讯云代金券