android setting中控制gps电源

2019-07-14 02:42发布

      android系统setting中的location&security选项下有一个“Use GPS satellites”选项框,这个选项框的是否勾选从软件上决定系统是否提供gps服务,但它并不能对硬件gps模块的开关起到作用,无论它勾选与否gps芯片实际上一直是处在运行状态的。笔者对android setting中的代码进行了一些改动,效果是可以通过“Use GPS satellites”选项的勾选与否控制gps模块的电源开关,以此降低系统能耗,提高性能。大体上的方法是在setting的代码包中加入了一个自己编写的简单的jni,由它调用内核中的电源控制gps的硬开关。 一java部分 “Use GPS satellites”的勾选决定了android 系统api中的locationmanager类是否加载gps服务,表现在代码中就是是否接受“gps”这个字符串作为参数。我们在这里要做的就是在setting的代码发送“gps”参数的同时,加入一个通过jni实现的开关gps电源的函数。 实现代码: /packages/apps/Settings/src/com/android/settingsSecuritySettings.java->onPreferenceTreeClick 1) …… } else if (preference == mGps) { boolean enabled = mGps.isChecked(); Settings.Secure.setLocationProviderEnabled(getContentResolver(), LocationManager.GPS_PROVIDER, enabled); //++++++++++++++++此处调用gps开关电的功能函数 Native.switch_to(enabled); //++++++++++++++++ add by chris if (mAssistedGps != null) { 2) …… //+++++++++++++此处声明jni的本地库,以及所需要调用的功能函数,在这里将功能函数封装在自定义的Native类中,关于jni调用的具体//规则具体规则请研究//development/samples/SimpleJNI class Native { static { // The runtime will add "lib" on the front and ".o" on the end of the name supplied to loadLibrary. System.loadLibrary("gps_power"); } static native int switch_to(boolean a); } //+++++++++++++++++++++++++++++++ add by chris 二JNi部分 Java代码中只涉及到jni的调用,这里我们新建一个名叫jni的文件夹在/packages/apps/Settings路径下以用于存放c++代码。(只要代码内容和编译路径正确,文件名的位置和名称可以自行设定,不必非要放在setting下),这个文件夹内包含一个c++源文件gps_power.cpp和一个android.mk Gps_power.cpp代码可以参考/development/samples/SimpleJNI/native.cpp,这里我们把gps开关功能的实现放在 switch_to函数中。 实现代码: /packages/apps/Settings/jni/gps_power.cpp / packages/apps/Settings/jni/android.mk static jint switch_to(JNIEnv *env, jobject thiz, jboolean enable) { int fd; char buf[256]; fd= open("/dev/device-pm",O_RDWR|O_CREAT);//打开负责控制gps电源的硬件节点 LOGI("fd=%d,gps power switch to %d", fd,enable); ioctl(fd,3,enable); // 此处调用kernel代码中相关部分实现gps模块电源的控制 close(fd); return fd; } 下面的这个函数用于向android注册jni函数,左侧是在java调用中用的函数名,右侧是c或cpp中实际的函数名,中间的“(Z)”代表java调用时只有一个布尔型参数,I代表函数返回值为整型。 …… static JNINativeMethod methods[] = { {"switch_to", "(Z)I", (void*)switch_to }, }; 需要注意的是”static int registerNativeMethods” 函数中的第二个参数char* className,用于标识引用本段代码的java类,如笔者所用的java类即为com/android/settings/Native 三kernel部分 Kernel部分负责直接控制寄存器实现gps硬件系统的电源开关,笔者这里用到的硬件节点为/dev/device-pm,相关的系统调用功能号是3.由于不同开发板硬件设置不同,kernel中的实现代码也不尽相同。所以笔者在这里不做详细介绍,具体实现过程无非是向控制gps电源的端口发0或者发1。与那上层相对应的调用关系请查看有关驱动开发的书籍中ioctl相关章节。 最后一定要注意的是,gps模块的完全关电将会导致gps冷启动,从而大大延长gps定位时间。笔者所用的gps模块有一个Vbak引脚一直保持供电状态(耗电相比主电引脚低很多),所以可以保证主电关闭后不至于每次都冷启动。因此如果目标板gps模块上面没有这样一个备用电源引脚保持连接,不建议采用上述方法来给自己的板子省电。