第二十期 在Android中修改GPS定位数据的完整方案《手机就是开发板》 | 您所在的位置:网站首页 › 安卓系统怎么修改定位 › 第二十期 在Android中修改GPS定位数据的完整方案《手机就是开发板》 |
https://blog.csdn.net/aggresss/article/details/54323034 现在很多的应用都是基于位置服务的,而且把位置服务作为重要的参考标准,其实这是很不安全的,位置信息的数据未经过任何加密,而且是从我们的手机中发送出去的,所以是可以修改的。这一期我们来探讨一下如何修改手机中的定位信息。太基础的原理我就不多说了,可以参考前几期文章。 先整理一下思路,Android在开发者模式下有一个"允许模拟位置选项",它是location service加载 MOCK location provider 实现的,通过这种线程注入的方式修改GPS信息是hacker们最喜欢的方式,但现在很多应用已经可以检测到这种注入方式而被屏蔽掉,也就是说如果我们只在APP层面上想解决方法总是有被检测出来的可能。那我们就得把问题往深了想,通过修改最底层的GPS数据来欺骗APP,在Framework层面上没有任何修改迹象,这样基于APP层面的检测机制就拿我们没有任何办法。 思路确定后我们来探讨实践路线,首先我们要建立一个管道,让我们想要定位的GPS数据提交到Android操作系统的最底层,也就是Linux Kernel层面;然后我们要修改 GPS的 location report 机制,让它从内核中提取到我们的数据,然后逐层上报到APP层。有点明修栈道暗度陈仓的感觉。 总体来说分成两部实现:1.建立到系统内核的数据管道;2.修改GPS上报机制。 这次实验使用的是闲置的小米3W手机,编译源码采用CyanogenMod-13,具体的编译环境搭建和编译方法请参考前几期文章。 因为Android系统从内核态到APP层要经过很多的层次,所以对于建立数据管道的步骤比较繁琐,我这里分成了5个步骤,对应5个层面来实现,每一步分别对应Android的 Kernel driver,HAL,JNI,Framework,Application。所有的代码我都已上传github中https://github.com/aggresss/PHDemo/ 这一期的代码在VirtualPosition 目录下。 下面描述一下实践步骤: =============分割线1============== 第一步,修改Kernel driver 进入 kernel/xiaomi/cancro/drivers 目录下,新建vp.h文件 #ifndef _VP_ANDROID_H_ #define _VP_ANDROID_H_ #include #include #define VP_DEVICE_NODE_NAME "vp" #define VP_DEVICE_FILE_NAME "vp" #define VP_DEVICE_PROC_NAME "vp" #define VP_DEVICE_CLASS_NAME "vp" typedef struct { int toggle; double virtual_latitude; double virtual_longitude; } VirtualPosition; struct vp_android_dev { int lamp; VirtualPosition val; struct semaphore sem; struct cdev dev; }; #endif新建vp.c文件 /******************************************* *include file and define functions *******************************************/ #include #include #include #include #include #include #include #include "vp.h" /*主设备和从设备号变量*/ static int vp_major = 0; static int vp_minor = 0; /*设备类别和设备变量*/ static struct class* vp_class = NULL; static struct vp_android_dev* vp_dev = NULL; /*传统的设备文件操作方法*/ static int vp_open(struct inode* inode, struct file* filp); static int vp_release(struct inode* inode, struct file* filp); static ssize_t vp_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos); static ssize_t vp_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos); /*设备文件操作方法表*/ static struct file_operations vp_fops = { .owner = THIS_MODULE, .open = vp_open, .release = vp_release, .read = vp_read, .write = vp_write, }; /*访问设置属性方法*/ static ssize_t vp_lamp_show(struct device* dev, struct device_attribute* attr, char* buf); static ssize_t vp_lamp_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count); /*定义设备属性*/ static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, vp_lamp_show, vp_lamp_store); /******************************************* *define traditional file access *******************************************/ /*打开设备方法*/ static int vp_open(struct inode* inode, struct file* filp) { struct vp_android_dev* dev; /*将自定义设备结构体保存在文件指针的私有数据域中,以便访问设备时拿来用*/ dev = container_of(inode->i_cdev, struct vp_android_dev, dev); filp->private_data = dev; return 0; } /*设备文件释放时调用,空实现*/ static int vp_release(struct inode* inode, struct file* filp) { return 0; } /*读取设备的寄存器val的值*/ static ssize_t vp_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos) { ssize_t err = 0; struct vp_android_dev* dev = filp->private_data; /*同步访问*/ if(down_interruptible(&(dev->sem))) { return -ERESTARTSYS; } if(count < sizeof(dev->val)) { goto out; } /*将寄存器val的值拷贝到用户提供的缓冲区*/ if(copy_to_user(buf, &(dev->val), sizeof(dev->val))) { err = -EFAULT; goto out; } err = sizeof(dev->val); out: up(&(dev->sem)); return err; } /*写设备的寄存器值val*/ static ssize_t vp_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos) { struct vp_android_dev* dev = filp->private_data; ssize_t err = 0; /*同步访问*/ if(down_interruptible(&(dev->sem))) { return -ERESTARTSYS; } if(count != sizeof(dev->val)) { goto out; } /*将用户提供的缓冲区的值写到设备寄存器去*/ if(copy_from_user(&(dev->val), buf, count)) { err = -EFAULT; goto out; } err = sizeof(dev->val); out: up(&(dev->sem)); return err; } /******************************************* *define devfs access *******************************************/ /*读取寄存器lamp的值到缓冲区buf中,内部使用*/ static ssize_t __vp_get_lamp(struct vp_android_dev* dev, char* buf) { int lamp = 0; /*同步访问*/ if(down_interruptible(&(dev->sem))) { return -ERESTARTSYS; } lamp = dev->lamp; up(&(dev->sem)); return snprintf(buf, PAGE_SIZE, "%d\n", lamp); } /*把缓冲区buf的值写到设备寄存器lamp中去,内部使用*/ static ssize_t __vp_set_lamp(struct vp_android_dev* dev, const char* buf, size_t count) { int lamp = 0; /*将字符串转换成数字*/ lamp = simple_strtol(buf, NULL, 10); /*同步访问*/ if(down_interruptible(&(dev->sem))) { return -ERESTARTSYS; } dev->lamp = lamp; up(&(dev->sem)); return count; } /*读取设备属性lamp*/ static ssize_t vp_lamp_show(struct device* dev, struct device_attribute* attr, char* buf) { struct vp_android_dev* hdev = (struct vp_android_dev*)dev_get_drvdata(dev); return __vp_get_lamp(hdev, buf); } /*写设备属性lamp*/ static ssize_t vp_lamp_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count) { struct vp_android_dev* hdev = (struct vp_android_dev*)dev_get_drvdata(dev); return __vp_set_lamp(hdev, buf, count); } /******************************************* *define proc access *******************************************/ /*读取设备寄存器lamp的值,保存在page缓冲区中*/ static ssize_t vp_proc_read(char* page, char** start, off_t off, int count, int* eof, void* data) { if(off > 0) { *eof = 1; return 0; } return __vp_get_lamp(vp_dev, page); } /*把缓冲区的值buff保存到设备寄存器lamp中去*/ static ssize_t vp_proc_write(struct file* filp, const char __user *buff, unsigned long len, void* data) { int err = 0; char* page = NULL; if(len > PAGE_SIZE) { printk(KERN_ALERT"The buff is too large: %lu.\n", len); return -EFAULT; } page = (char*)__get_free_page(GFP_KERNEL); if(!page) { printk(KERN_ALERT"Failed to alloc page.\n"); return -ENOMEM; } /*先把用户提供的缓冲区值拷贝到内核缓冲区中去*/ if(copy_from_user(page, buff, len)) { printk(KERN_ALERT"Failed to copy buff from user.\n"); err = -EFAULT; goto out; } err = __vp_set_lamp(vp_dev, page, len); out: free_page((unsigned long)page); return err; } /*创建/proc/vp文件*/ static void vp_create_proc(void) { struct proc_dir_entry *entry; entry = create_proc_entry(VP_DEVICE_PROC_NAME, 0, NULL); if(entry) { entry->read_proc = vp_proc_read; entry->write_proc = vp_proc_write; } } /*删除/proc/vp文件*/ static void vp_remove_proc(void) { remove_proc_entry(VP_DEVICE_PROC_NAME, NULL); } /******************************************* *define load and remove function *******************************************/ /*初始化设备*/ static int __vp_setup_dev(struct vp_android_dev* dev) { int err; dev_t devno = MKDEV(vp_major, vp_minor); memset(dev, 0, sizeof(struct vp_android_dev)); cdev_init(&(dev->dev), &vp_fops); dev->dev.owner = THIS_MODULE; dev->dev.ops = &vp_fops; /*注册字符设备*/ err = cdev_add(&(dev->dev),devno, 1); if(err) { return err; } /*初始化信号量和寄存器lamp, val的值*/ sema_init(&(dev->sem), 1); dev->lamp = 7777; dev->val.toggle = 1; dev->val.virtual_latitude = 45.104108; dev->val.virtual_longitude = 130.816878; return 0; } /*模块加载方法*/ static int __init vp_init(void){ int err = -1; dev_t dev = 0; struct device* temp = NULL; printk(KERN_ALERT"Initializing vp device.\n"); /*动态分配主设备和从设备号*/ err = alloc_chrdev_region(&dev, 0, 1, VP_DEVICE_NODE_NAME); if(err < 0) { printk(KERN_ALERT"Failed to alloc char dev region.\n"); goto fail; } vp_major = MAJOR(dev); vp_minor = MINOR(dev); /*分配helo设备结构体变量*/ vp_dev = kmalloc(sizeof(struct vp_android_dev), GFP_KERNEL); if(!vp_dev) { err = -ENOMEM; printk(KERN_ALERT"Failed to alloc vp_dev.\n"); goto unregister; } /*初始化设备*/ err = __vp_setup_dev(vp_dev); if(err) { printk(KERN_ALERT"Failed to setup dev: %d.\n", err); goto cleanup; } /*在/sys/class/目录下创建设备类别目录vp*/ vp_class = class_create(THIS_MODULE, VP_DEVICE_CLASS_NAME); if(IS_ERR(vp_class)) { err = PTR_ERR(vp_class); printk(KERN_ALERT"Failed to create vp class.\n"); goto destroy_cdev; } /*在/dev/目录和/sys/class/vp目录下分别创建设备文件vp*/ temp = device_create(vp_class, NULL, dev, "%s", VP_DEVICE_FILE_NAME); if(IS_ERR(temp)) { err = PTR_ERR(temp); printk(KERN_ALERT"Failed to create vp device."); goto destroy_class; } /*在/sys/class/vp/vp目录下创建属性文件val*/ err = device_create_file(temp, &dev_attr_val); if(err < 0) { printk(KERN_ALERT"Failed to create attribute val."); goto destroy_device; } dev_set_drvdata(temp, vp_dev); /*创建/proc/vp文件*/ vp_create_proc(); printk(KERN_ALERT"Succedded to initialize vp device.\n"); return 0; destroy_device: device_destroy(vp_class, dev); destroy_class: class_destroy(vp_class); destroy_cdev: cdev_del(&(vp_dev->dev)); cleanup: kfree(vp_dev); unregister: unregister_chrdev_region(MKDEV(vp_major, vp_minor), 1); fail: return err; } /*模块卸载方法*/ static void __exit vp_exit(void) { dev_t devno = MKDEV(vp_major, vp_minor); printk(KERN_ALERT"Destroy vp device.\n"); /*删除/proc/vp文件*/ vp_remove_proc(); /*销毁设备类别和设备*/ if(vp_class) { device_destroy(vp_class, MKDEV(vp_major, vp_minor)); class_destroy(vp_class); } /*删除字符设备和释放设备内存*/ if(vp_dev) { cdev_del(&(vp_dev->dev)); kfree(vp_dev); } /*释放设备号*/ unregister_chrdev_region(devno, 1); } MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Virtualposition Driver"); module_init(vp_init); module_exit(vp_exit);添加 Kconfig 文件 config VP tristate "Virtual Position Driver" default n help This is the virtual position driver.添加 Makefile 文件 obj-$(CONFIG_VP) += vp.o修改 drivers/Kconfig 文件 在menu "Device Drivers"和endmenu之间添加一行: source "drivers/vp/Kconfig"修改drivers/Makefile文件,添加一行: obj-$(CONFIG_HELLO) += vp/修改 arch/arm/configs目录下的cyanogen_cancro_defconfig 文件,在文件末尾加入 # CONFIG_VP CONFIG_VP=y=============分割线2============== 第二步,修改HAL 进入 ./hardware/libhardware/include/hardware 目录,新建 vp.h 文件 #ifndef ANDROID_VP_INTERFACE_H #define ANDROID_VP_INTERFACE_H #include __BEGIN_DECLS /*定义模块ID*/ #define VP_HARDWARE_MODULE_ID "vp" //typedef enum{false, true} bool; /*define virtual position structrue*/ typedef struct { int toggle; double virtual_latitude; double virtual_longitude; } VirtualPosition; /*硬件模块结构体*/ struct vp_module_t { struct hw_module_t common; }; /*硬件接口结构体*/ struct vp_device_t { struct hw_device_t common; int fd; int (*set_val)(struct vp_device_t* dev, VirtualPosition val); int (*get_val)(struct vp_device_t* dev, VirtualPosition* val); }; __END_DECLS #endif进入到 hardware/libhardware/modules 目录,新建vp目录,并添加vp.c文件 #define LOG_TAG "VpStub" #include #include #include #include #include #include #define DEVICE_NAME "/dev/vp" #define MODULE_NAME "Vp" #define MODULE_AUTHOR "[email protected]" /*设备打开和关闭接口*/ static int vp_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device); static int vp_device_close(struct hw_device_t* device); /*设备访问接口*/ static int vp_set_val(struct vp_device_t* dev, VirtualPosition val); static int vp_get_val(struct vp_device_t* dev, VirtualPosition* val); /*模块方法表*/ static struct hw_module_methods_t vp_module_methods = { open: vp_device_open }; /*模块实例变量*/ struct vp_module_t HAL_MODULE_INFO_SYM = { common: { tag: HARDWARE_MODULE_TAG, version_major: 1, version_minor: 0, id: VP_HARDWARE_MODULE_ID, name: MODULE_NAME, author: MODULE_AUTHOR, methods: &vp_module_methods, } }; static int vp_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device) { struct vp_device_t* dev;dev = (struct vp_device_t*)malloc(sizeof(struct vp_device_t)); if(!dev) { ALOGE("Vp Stub: failed to alloc space"); return -EFAULT; } memset(dev, 0, sizeof(struct vp_device_t)); dev->common.tag = HARDWARE_DEVICE_TAG; dev->common.version = 0; dev->common.module = (hw_module_t*)module; dev->common.close = vp_device_close; dev->set_val = vp_set_val;dev->get_val = vp_get_val; if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) { ALOGE("Vp Stub: failed to open /dev/vp -- %s.", strerror(errno));free(dev); return -EFAULT; } *device = &(dev->common); ALOGI("Vp Stub: open /dev/vp successfully."); return 0; } static int vp_device_close(struct hw_device_t* device) { struct vp_device_t* vp_device = (struct vp_device_t*)device; if(vp_device) { close(vp_device->fd); free(vp_device); } return 0; } static int vp_set_val(struct vp_device_t* dev, VirtualPosition val) { ALOGI("Vp Stub: set value %d to device.", val); write(dev->fd, &val, sizeof(val)); return 0; } static int vp_get_val(struct vp_device_t* dev, VirtualPosition* val) { if(!val) { ALOGE("Vp Stub: error val pointer"); return -EFAULT; } read(dev->fd, val, sizeof(*val)); ALOGI("Vp Stub: get value %d from device", *val); return 0; }继续在vp目录下新建Android.mk文件: LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_PRELINK_MODULE := false LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw LOCAL_SHARED_LIBRARIES := liblog LOCAL_SRC_FILES := vp.c LOCAL_MODULE := vp.default include $(BUILD_SHARED_LIBRARY)=============分割线3============== 第三步,修改JNI 进入 frameworks/base/services/core/jni 目录,新建com_android_server_VirtualPositionService.cpp文件 #define LOG_TAG "VirtualPositionService" #include "jni.h" #include "JNIHelp.h" #include "android_runtime/AndroidRuntime.h" #include #include #include #include #include namespace android { VirtualPosition virtual_position = {1, 0.0, 0.0}; /*在硬件抽象层中定义的硬件访问结构体,参考*/ struct vp_device_t* vp_device = NULL; /*通过硬件抽象层定义的硬件访问接口设置硬件寄存器val的值*/ static void vp_setVal() { ALOGI("VirtualPosition JNI: set value to device."); if(!vp_device) { ALOGI("VirtualPosition JNI: device is not open."); return; } vp_device->set_val(vp_device, virtual_position); } /*通过硬件抽象层定义的硬件访问接口读取硬件寄存器val的值*/ static void vp_getVal() { if(!vp_device) { ALOGI("VirtualPosition JNI: device is not open."); } vp_device->get_val(vp_device, &virtual_position); ALOGI("VirtualPosition JNI: get value from device."); } /*通过硬件抽象层定义的硬件模块打开接口打开硬件设备*/ static inline int vp_device_open(const hw_module_t* module, struct vp_device_t** device) { return module->methods->open(module, VP_HARDWARE_MODULE_ID, (struct hw_device_t**)device); } /*通过硬件模块ID来加载指定的硬件抽象层模块并打开硬件*/ static jboolean vp_init(JNIEnv* env, jclass clazz) { vp_module_t* module; ALOGI("VirtualPosition JNI: initializing......"); if(hw_get_module(VP_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) { ALOGI("VirtualPosition JNI: vp Stub found."); if(vp_device_open(&(module->common), &vp_device) == 0) { ALOGI("VirtualPosition JNI: vp device is open."); return 0; } ALOGE("VirtualPosition JNI: failed to open vp device."); return -1; } ALOGE("VirtualPosition JNI: failed to get vp stub module."); return -1; } static void android_server_VirtualPositionService_set_virtual_toggle(JNIEnv* env, jclass clazz, jint tog) { virtual_position.toggle = tog; vp_setVal(); } static jint android_server_VirtualPositionService_get_virtual_toggle(JNIEnv* env, jclass clazz) { vp_getVal(); return virtual_position.toggle; } static void android_server_VirtualPositionService_set_virtual_latitude(JNIEnv* env, jclass clazz, jdouble vlat) { virtual_position.virtual_latitude = vlat; vp_setVal(); } static jdouble android_server_VirtualPositionService_get_virtual_latitude(JNIEnv* env, jclass clazz) { vp_getVal(); return virtual_position.virtual_latitude; } static void android_server_VirtualPositionService_set_virtual_longitude(JNIEnv* env, jclass clazz, jdouble vlon) { virtual_position.virtual_longitude = vlon; vp_setVal(); } static jdouble android_server_VirtualPositionService_get_virtual_longitude(JNIEnv* env, jclass clazz) { vp_getVal(); return virtual_position.virtual_longitude; } /*JNI方法表*/ static const JNINativeMethod method_table[] = { {"init_native", "()Z", (void*)vp_init}, {"native_set_virtual_toggle", "(I)V", (void*)android_server_VirtualPositionService_set_virtual_toggle}, {"native_get_virtual_toggle", "()I", (void*)android_server_VirtualPositionService_get_virtual_toggle}, {"native_set_virtual_latitude", "(D)V", (void*)android_server_VirtualPositionService_set_virtual_latitude}, {"native_get_virtual_latitude", "()D", (void*)android_server_VirtualPositionService_get_virtual_latitude}, {"native_set_virtual_longitude", "(D)V", (void*)android_server_VirtualPositionService_set_virtual_longitude}, {"native_get_virtual_longitude", "()D", (void*)android_server_VirtualPositionService_get_virtual_longitude}, }; /*注册JNI方法*/ int register_android_server_VirtualPositionService(JNIEnv *env) { return jniRegisterNativeMethods(env, "com/android/server/VirtualPositionService", method_table, NELEM(method_table)); } };修改同目录下的onload.cpp文件,首先在namespace android增加com_android_server_VirtualPositionService函数声明: namespace android { .............................................................................................. int register_android_server_VirtualPositionService(JNIEnv *env); }; 在JNI_onLoad增加register_android_server_VirtualPositionService函数调用: extern "C" jint JNI_onLoad(JavaVM* vm, void* reserved) { ................................................................................................. register_android_server_VirtualPositionService(env); ................................................................................................. }修改同目录下的Android.mk文件,在LOCAL_SRC_FILES变量中增加一行: LOCAL_SRC_FILES:= \ com_android_server_AlarmManagerService.cpp \ com_android_server_BatteryService.cpp \ com_android_server_InputManager.cpp \ com_android_server_LightsService.cpp \ com_android_server_PowerManagerService.cpp \ com_android_server_SystemServer.cpp \ com_android_server_UsbService.cpp \ com_android_server_VibratorService.cpp \ com_android_server_location_GpsLocationProvider.cpp \ com_android_server_VirtualPositionService.cpp \ onload.cpp=============分割线4============== 第四步,修改Framework 进入到frameworks/base/core/java/android/os目录,新增VirtualPositionService.aidl接口定义文件 package android.os; interface IVirtualPositionService { void setVirtualToggle(int tog); int getVirtualToggle(); void setVirtualLatitude(double vlat); double getVirtualLatitude(); void setVirtualLongitude(double vlon); double getVirtualLongitude(); }然后进入 frameworks/base目录,打开Android.mk文件,修改LOCAL_SRC_FILES变量的值,增加IVirtualPosition.aidl源文件: LOCAL_SRC_FILES += / .................................................................... core/java/android/os/IVibratorService.aidl / core/java/android/os/IVirtualPosition.aidl / core/java/android/service/urlrenderer/IUrlRendererService.aidl / .....................................................................进入到frameworks/base/services/java/com/android/server目录,新增VirtualPositionService.java文件 package com.android.server; import android.content.Context; import android.os.IVirtualPositionService; import android.util.Slog; public class VirtualPositionService extends IVirtualPositionService.Stub { private static final String TAG = "VirtualPositionService"; VirtualPositionService() { init_native(); } public void setVirtualToggle(int tog) { native_set_virtual_toggle(tog); } public int getVirtualToggle(){ return native_get_virtual_toggle(); } public void setVirtualLatitude(double vlat) { native_set_virtual_latitude(vlat); } public double getVirtualLatitude(){ return native_get_virtual_latitude(); } public void setVirtualLongitude(double vlon) { native_set_virtual_longitude(vlon); } public double getVirtualLongitude() { return native_get_virtual_longitude(); } private static native boolean init_native(); private static native void native_set_virtual_toggle(int tog); private static native int native_get_virtual_toggle(); private static native void native_set_virtual_latitude(double vlat); private static native double native_get_virtual_latitude(); private static native void native_set_virtual_longitude(double vlon); private static native double native_get_virtual_longitude(); };修改同目录的SystemServer.java文件,在ServerThread::run函数中增加加载VirtualPositionService的代码: @Override public void run() { .................................................................................... try { Slog.i(TAG, "DiskStats Service"); ServiceManager.addService("diskstats", new DiskStatsService(context)); } catch (Throwable e) { Slog.e(TAG, "Failure starting DiskStats Service", e); } try { Slog.i(TAG, "VirtualPosition Service"); ServiceManager.addService("virtualposition", new VirtualPositionService()); } catch (Throwable e) { Slog.e(TAG, "Failure starting VirtualPosition Service", e); } ...................................................................................... }然后需要修改sepolicy文件,具体的文件在github上,请下载使用。 =============分割线5============== 第五步,修改application APP的文件比较多,请到github上下载,这里只贴具体的逻辑代码: package com.example.phdemo.myapplication; import android.os.RemoteException; import android.app.Activity; import android.os.ServiceManager; import android.os.Bundle; import android.widget.CompoundButton; import android.os.IVirtualPositionService; import android.os.RemoteException; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.ToggleButton; import android.widget.CompoundButton.OnCheckedChangeListener; public class MainActivity extends Activity implements View.OnClickListener { private final static String LOG_TAG = "com.example.phdemo.virtualposition"; private IVirtualPositionService virtualpositionService = null; private ToggleButton toggleButton = null; private EditText altitudeValueText = null; private EditText longitudeValueText = null; private Button getButton = null; private Button setButton = null; private Button clearButton = null; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); virtualpositionService = IVirtualPositionService.Stub.asInterface( ServiceManager.getService("virtualposition")); toggleButton=(ToggleButton)findViewById(R.id.toggleButton); altitudeValueText = (EditText)findViewById(R.id.altitude_value); longitudeValueText = (EditText)findViewById(R.id.longitude_value); getButton = (Button)findViewById(R.id.button_get); setButton = (Button)findViewById(R.id.button_set); clearButton = (Button)findViewById(R.id.button_clear); getButton.setOnClickListener(this); setButton.setOnClickListener(this); clearButton.setOnClickListener(this); try{ int val_tog = virtualpositionService.getVirtualToggle(); if(val_tog == 1){ toggleButton.setChecked(true); }else{ toggleButton.setChecked(false); } } catch (Exception e) {} toggleButton.setOnCheckedChangeListener(new OnCheckedChangeListener(){ public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) { toggleButton.setChecked(isChecked); try{ virtualpositionService.setVirtualToggle(isChecked?1:0); }catch(Exception e){} } }); Log.i(LOG_TAG, "VirtualPosition Activity Created"); } @Override public void onClick(View v) { if(v.equals(getButton)) { try { double val_altitude = virtualpositionService.getVirtualLatitude(); String text_altitude = String.valueOf(val_altitude); altitudeValueText.setText(text_altitude); double val_longitude = virtualpositionService.getVirtualLongitude(); String text_longitude = String.valueOf(val_longitude); longitudeValueText.setText(text_longitude); int val_tog = virtualpositionService.getVirtualToggle(); if(val_tog == 1){ toggleButton.setChecked(true); }else{ toggleButton.setChecked(false); } } catch (Exception e) { Log.e(LOG_TAG, "Remote Exception while reading value from GpsLocationProvider."); } } else if(v.equals(setButton)) { try { String text_altitude = altitudeValueText.getText().toString(); String text_longitude = longitudeValueText.getText().toString(); double val_altitude = Double.parseDouble(text_altitude); double val_longitude = Double.parseDouble(text_longitude); virtualpositionService.setVirtualLatitude(val_altitude); virtualpositionService.setVirtualLongitude(val_longitude); } catch (Exception e) { Log.e(LOG_TAG, "Remote Exception while writing value to GpsLocationProvider."); } } else if(v.equals(clearButton)) { String text = ""; altitudeValueText.setText(text); longitudeValueText.setText(text); } } }=============分割线6============== 最后一步,在JNI层面修改location report 机制。 进入 frameworks/base/services/core/jni 目录,修改com_android_server_location_GpsLocationProvider.cpp文件: 在全局变量部分加入 // add by aggresss static int vp_fd = open("/dev/vp", O_RDWR); static VirtualPosition vp_val;修改location_callback函数: static void location_callback(GpsLocation* location) { JNIEnv* env = AndroidRuntime::getJNIEnv(); //add by aggresss read(vp_fd, &vp_val, sizeof(VirtualPosition)); if(vp_val.toggle == 1){ env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags, (jdouble)vp_val.virtual_latitude, (jdouble)vp_val.virtual_longitude, (jdouble)location->altitude, (jfloat)location->speed, (jfloat)location->bearing, (jfloat)location->accuracy, (jlong)location->timestamp); checkAndClearExceptionFromCallback(env, __FUNCTION__); } else{ env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags, (jdouble)location->latitude, (jdouble)location->longitude, (jdouble)location->altitude, (jfloat)location->speed, (jfloat)location->bearing, (jfloat)location->accuracy, (jlong)location->timestamp); checkAndClearExceptionFromCallback(env, __FUNCTION__); } }=============我是完成的分割线============== 完成后,重新编译固件,开机后启动VirtualPosition的APP,设置你想要的坐标,想在哪就在哪了。 |
CopyRight 2018-2019 实验室设备网 版权所有 |