Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Android GPS学习 (一) :GPS 启动流程

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

作者头像
用户7557625
发布于 2020-07-15 06:09:00
发布于 2020-07-15 06:09:00
2.4K00
代码可运行
举报
运行总次数:0
代码可运行

一、Settings

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void onSwitchChanged(Switch switchView, boolean isChecked) {
    mLocationEnabler.setLocationEnabled(isChecked);
}

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 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方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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方法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void enable() {
    synchronized (mLock) {
        if (mEnabled) return;
        mEnabled = true;
    }

    sendMessage(ENABLE, 1, null);
}

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{"native_init", "()Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_init)},
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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的定义:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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;
};
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/05/15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Android9.0 蓝牙开启流程
/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothSwitchPreferenceController.java
用户7557625
2020/07/15
2.1K0
ActivityManagerService 启动初探
在之前的Android SystemServer启动(二)中,分析到在SystemServer中会启动大量的Service,其中就有一个比较特殊的Service,它就是ActivityManagerService。
Rouse
2021/01/12
9440
Android源码阅读技巧--查找开发者选项中显示触摸操作源码
在开发者模式下,在开发者选项中,可以勾选“显示触摸操作”,然后只要点击屏幕就会在点击的位置有圈圈显示。如何找到绘制圈圈的代码部分,有什么技巧来阅读代码量这么大的android系统源码呢?以下请跟着小老弟我来一起分析吧。
啊源股
2019/09/29
1.7K0
APK安装流程详解14——PMS中的新安装流程上(拷贝)补充
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null) 要看这个方法内部执行,首先要知道这个mContext是什么,我们知道这个mContext是通过PackageManagerService的main方法传入的,所以这个mContext就是SystemServer里面的mSystemContext。 代码在SystemServer.java 366行如下:
隔壁老李头
2018/08/30
3.1K0
APK安装流程详解14——PMS中的新安装流程上(拷贝)补充
Android GPS学习 (二) :GPS 服务启动以及初始化流程
SystemServer.java的startOtherServices方法中添加LocationManagerService方法的代码如下,
用户7557625
2020/07/15
1.7K0
Android热修复学习之旅——Andfix框架完全解析
Android热修复学习之旅开篇——热修复概述 Android热修复学习之旅——HotFix完全解析 Android热修复学习之旅——Tinker接入全攻略
老马的编程之旅
2022/06/22
1.1K0
Android热修复学习之旅——Andfix框架完全解析
Android carservice架构及启动流程
这个文件中列出了汽车系统中的专有模块(首字母大写的模块基本上都是汽车系统中专有的App):
wizzie
2022/09/28
2.6K0
Android carservice架构及启动流程
Android 蓝牙源码学习笔记
上文介绍了蓝牙基本原理和潜在的攻击面,但实现部分介绍不多。本文作为补充,以 Android 中的蓝牙协议栈为例,学习并了解在实际系统中蓝牙的工程实现。
evilpan
2023/02/12
2.6K0
Android 蓝牙源码学习笔记
Android 上层蓝牙enable流程
基于Android9.0 Amlogic代码分析, 蓝牙应用通过 Binder 与蓝牙进程进行通信。蓝牙进程使用 JNI 与蓝牙堆栈通信,并向开发者提供对各种蓝牙配置文件的访问权限。下图显示了蓝牙堆栈的常规结构:
小蚂蚁与大象
2021/12/16
1.4K0
Android 上层蓝牙enable流程
Android内存篇(二)---JVMTI在Anroid8.1下的使用
上一篇《Android内存篇(一)---使用JVMTI监控应用》中已经介绍了Android的JVMTI内存监控,文章最后我也提到了,虽然代码中anroid8.0通过反射开启JVMTI的监控,但是项目中的代码并不能用,在JNI里C++报空指针的问题,也是因为自己的产品中用的Android设备正好是8.1的,实际使用时发现的这个问题,所以就有了这篇针对Android8,1的JVMTI使用
Vaccae
2022/05/25
6450
Android内存篇(二)---JVMTI在Anroid8.1下的使用
Android开机动画启动流程
在Android设备开机启动时,会展示Android开机动画,用于增加用户体验和展示设备品牌等信息。它也是Android系统启动的一部分。开机动画是由bootanimation负责的,因此首先先了解下bootanimation是如何启动的。
八归少年
2023/11/14
7420
Android Framework学习(五)之应用进程启动流程
在之前的博客中我们学习了Launcher的启动流程,在SystemServer进程执行完成,各种系统服务启动完成之后,会调用ActivityManagerService中的systemReady()方法,在systemReady()方法中会执行Launcher启动的相关逻辑,本篇博客,我们将一起学习应用程序进程的启动流程,注意:这里是“应用程序进程启动过程”,而不是应用程序启动过程
老马的编程之旅
2022/06/22
6330
(七十)Android O Service启动流程梳理——bindService
前言:最近在处理anr问题的时候迫切需要搞清楚service的启动流程,抽时间梳理一下。
全栈程序员站长
2022/09/05
8220
App进程启动流程
在上一节Activity的启动流程中,当app进程不存在(第一次启动)时,会先去创建进程。这里我们通过源码来解读app进程的启动流程。
用户2929716
2018/08/23
3K0
Android 用户态启动流程分析
从硬件上电启动到终端软件可用是一个漫长而复杂的过程,我们在开心享受着丰富的应用程序时候,可能并没想到这其中所包含的工程师心血。
evilpan
2023/02/12
9890
Android内存篇(一)---使用JVMTI监控应用
一般产品或项目前期都是以快速实现,上线的方式来完成,在生产环境中再开始进行优化,而Android的APP优化,比较重点的还是内存优化,因为每个APP都分配的最大内存,像内存泄露,内存抖动等慢慢都会让APP出来OOM崩溃的情况,最近也是一直在学习和研究内存优化这块,也是在实践中记录笔记。
Vaccae
2022/05/25
2.5K0
Android内存篇(一)---使用JVMTI监控应用
APK安装流程详解8——PackageManagerService的启动流程(下)
那我们就来看下scanPackageLI(PackageParser.Package, int, int, long, UserHandle)方法
隔壁老李头
2018/08/30
2.7K0
【Android 安全】DEX 加密 ( Application 替换 | 分析 ContentProvider 组件中调用 getApplication() 获取的 Application )
创建 自定义 ContentProvider , 并在其 onCreate 方法中打印上下文信息 :
韩曙亮
2023/03/29
1.1K0
【Android 安全】DEX 加密 ( Application 替换 | 分析 ContentProvider 组件中调用 getApplication() 获取的 Application )
PackageManagerService启动流程源码解析
PackageManagerService,是Android系统中核心服务之一,管理着所有跟package相关的工作,常见的比如安装、卸载应用。 PKMS服务也是通过binder进行通信,IPackageManager.aidl由工具转换后自动生成binder的服务端IPackageManager.Stub和客户端IPackageManager.Stub.Proxy,具体关系如下:
老马的编程之旅
2022/06/22
1.2K0
PackageManagerService启动流程源码解析
Android 亮度自动调节
下拉状态栏有个亮度的进度条,如果开启了亮度自动调节开关,会随着周围光线变化,这个进度条也会随着变化,接下来就是看看这个功能是如何实现的。
吴小龙同學
2019/12/11
2.6K0
相关推荐
Android9.0 蓝牙开启流程
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验