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 <linux/cdev.h> ?
#include <linux/semaphore.h> ?#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 <linux/init.h> ?
#include <linux/module.h> ?
#include <linux/types.h> ?
#include <linux/fs.h> ?
#include <linux/proc_fs.h> ?
#include <linux/device.h> ?
#include <asm/uaccess.h> ?#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 VPtristate "Virtual Position Driver"default nhelpThis 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 <hardware/hardware.h> ?
__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 <hardware/hardware.h> ?
#include <hardware/vp.h> ?
#include <fcntl.h> ?
#include <errno.h> ?
#include <cutils/log.h> ?
#include <cutils/atomic.h> ?#define DEVICE_NAME "/dev/vp" ?
#define MODULE_NAME "Vp" ?
#define MODULE_AUTHOR "aggresss@163.com" ?/*設備打開和關閉接口*/ ?
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 <utils/misc.h> ?
#include <utils/Log.h> ?
#include <hardware/hardware.h> ?
#include <hardware/vp.h> ?
#include <stdio.h> ?namespace android ?
{ ?VirtualPosition virtual_position = {1, 0.0, 0.0};/*在硬件抽象層中定義的硬件訪問結構體,參考<hardware/vp.h>*/ ?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. */@Overridepublic 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");}@Overridepublic 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 aggresssread(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,設置你想要的坐標,想在哪就在哪了。
????????
? ? ? ? ??
總結
以上是生活随笔為你收集整理的第二十期 在Android中修改GPS定位数据的完整方案《手机就是开发板》的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。