第二十期 在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 "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

#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,设置你想要的坐标,想在哪就在哪了。

相关推荐

‎App Store 上的“17LIVE
bet36365首页

‎App Store 上的“17LIVE

📅 07-06 👁️ 5454
虚拟机linux系统如何安装
bet36365首页

虚拟机linux系统如何安装

📅 09-12 👁️ 6234
宁波颐高、亚细亚、天一数码(组装电脑配件、笔记本、最大)
365天免费观看完整版电影

宁波颐高、亚细亚、天一数码(组装电脑配件、笔记本、最大)

📅 09-19 👁️ 6152